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 <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <zlib.h>
-
- #include "install.h"
- #include "intl.h"
- #include "kbd.h"
- #include "kickstart.h"
- #include "log.h"
- #include "newt.h"
- #include "windows.h"
-
- struct defaultKeyboardByLang {
- char * lang, * keyboard;
- } defaultKeyboards[] = {
- { "fi", "fi-latin1" },
- { "se", "se-latin1" },
- { "no", "no-latin1" },
- { "cz", "cz-lat2" },
- { "tr", "trq" },
- { NULL, NULL } };
-
- /* 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(char ** keymap) {
- int num = -1;
- int rc;
- gzFile f;
- struct kmapHeader hdr;
- struct kmapInfo * infoTable;
- char ** argv;
- int argc;
- char ** kbds;
- char buf[16384]; /* I hope this is big enough */
- int i;
- char * defkbd = keymap ? *keymap : NULL;
- struct defaultKeyboardByLang * kbdEntry;
-
- /*if (testing) return 0;*/
-
- if (!defkbd && getenv("LANG")) {
- kbdEntry = defaultKeyboards;
- while (kbdEntry->lang &&
- strcmp(kbdEntry->lang, getenv("LANG")))
- kbdEntry++;
- if (kbdEntry->keyboard) defkbd = kbdEntry->keyboard;
- }
- if (!defkbd) defkbd = "us";
-
- 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;
- }
-
- if (kickstart) {
- if (!ksGetCommand(KS_CMD_KEYBOARD, NULL, &argc, &argv)) {
- if (argc < 2) {
- logMessage("no argument passed to keyboard "
- "kickstart command");
- } else {
- for (i = 0; i < hdr.numEntries; i++)
- if (!strcmp(infoTable[i].name, argv[1])) break;
- if (i < hdr.numEntries)
- num = i;
- else
- newtWinMessage("Kickstart Error", "Ok", "Bad keymap "
- "name %s passed to kickstart command.",
- argv[1]);
- }
- }
- }
-
- if (num == -1 ) {
- kbds = alloca(sizeof(*kbds) * (hdr.numEntries + 1));
- for (i = 0; i < hdr.numEntries; i++) {
- kbds[i] = infoTable[i].name;
- if (!strcmp(infoTable[i].name, defkbd))
- num = i;
- }
-
- kbds[i] = NULL;
-
- rc = newtWinMenu(_("Keyboard Type"),
- _("What type of keyboard do you have?"),
- 40, 5, 5, 8, kbds, &num, _("Ok"), /*_("Back"),*/ NULL);
- if (rc == 2) return INST_CANCEL;
- }
-
- 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);
-
- if (keymap) *keymap = strdup(infoTable[num].name);
-
- 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=%s\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 != '=')
- chptr--;
- if (*chptr == '.')
- *chptr-- = '\0';
-
- while (chptr > buf && *chptr != '/' && *chptr != '=')
- chptr--;
- if (*chptr == '/' || *chptr == '=')
- chptr++;
-
- *keymap = strdup(chptr);
-
- return 0;
- }
-