home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
kbd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-09
|
6KB
|
265 lines
#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 "kickstart.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(char ** keymap) {
newtComponent form, okay, listbox, answer;
int num = -1;
int rc;
gzFile f;
struct kmapHeader hdr;
struct kmapInfo * infoTable;
char ** argv;
int argc;
char buf[16384]; /* I hope this is big enough */
int i;
if (testing) return 0;
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 ) {
newtCenteredWindow(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);
newtFormDestroy(form);
newtPopWindow();
}
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=\"/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;
}