diff options
Diffstat (limited to 'loader2/kbd.c')
-rw-r--r-- | loader2/kbd.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/loader2/kbd.c b/loader2/kbd.c new file mode 100644 index 000000000..e3149a29b --- /dev/null +++ b/loader2/kbd.c @@ -0,0 +1,194 @@ +/* + * kbd.c - keyboard handling + * + * Erik Troan <ewt@redhat.com> + * Matt Wilson <msw@redhat.com> + * Michael Fulbright <msf@redhat.com> + * Jeremy Katz <katzj@redhat.com> + * + * Copyright 1997 - 2002 Red Hat, Inc. + * + * This software may be freely redistributed under the terms of the GNU + * General Public License. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <alloca.h> +#include <errno.h> +#include <newt.h> +#include <stdlib.h> +#include <string.h> + +#include "loader.h" +#include "loadermisc.h" +#include "log.h" +#include "lang.h" +#include "windows.h" + +#include "../isys/stubs.h" +#include "../isys/lang.h" + +/* JKFIXME: these should just be included from isys somehow.. */ +/* define ask johnsonm@redhat.com where this came from */ +#define KMAP_MAGIC 0x8B39C07F +#define KMAP_NAMELEN 40 /* including '\0' */ + +struct kmapHeader { + int magic; + int numEntries; +}; + +struct kmapInfo { + int size; + char name[KMAP_NAMELEN]; +}; + +int chooseKeyboard(char ** keymap, char ** kbdtypep, int flags) { + int num = -1; + int rc; + gzFile f; + struct kmapHeader hdr; + struct kmapInfo * infoTable; + struct langInfo * languages; + int numLanguages; + char ** kbds; + char buf[16384]; /* I hope this is big enough */ + int i; + char * defkbd = keymap ? *keymap : NULL; + char *lang; + +#if defined(__s390__) || defined(__s390x__) + return LOADER_NOOP; +#endif + + if (FL_SERIAL (flags)) return LOADER_NOOP; + +#ifdef __sparc__ + { + int fd; + + fd = open("/dev/kbd", O_RDWR); + if (fd < 0) + kbdtype = KBDTYPE_PC; /* if PC keyboard, then there is no driver for /dev/kbd */ + else { + close(fd); + kbdtype = KBDTYPE_SUN; + } + } +#endif /* sparc */ + + numLanguages = getLangInfo(&languages, flags); + + lang = getenv("LANG"); + if (!defkbd && lang) { + for (i = 0; i < numLanguages; i++) { + if (!strncmp(languages[i].lc_all, lang, 2)) { + defkbd = languages[i].keyboard; + break; + } + } + } + + if (!defkbd) +#ifdef __sparc__ + if (kbdtype == KBDTYPE_SUN) + defkbd = "sunkeymap"; + else +#endif /* sparc drain bamage */ + defkbd = "us"; + + f = gunzip_open("/etc/keymaps.gz"); + if (!f) { + errorWindow("cannot open /etc/keymaps.gz: %s"); + return LOADER_ERROR; + } + + if (gunzip_read(f, &hdr, sizeof(hdr)) != sizeof(hdr)) { + errorWindow("failed to read keymaps header: %s"); + gunzip_close(f); + return LOADER_ERROR; + } + + logMessage("%d keymaps are available", hdr.numEntries); + + i = hdr.numEntries * sizeof(*infoTable); + infoTable = alloca(i); + if (gunzip_read(f, infoTable, i) != i) { + errorWindow("failed to read keymap information: %s"); + gunzip_close(f); + return LOADER_ERROR; + } + + /* JKFIXME: this actually looks how I want most of the kickstart loader + * stuff to look. but since I've not stubbed kickstart in yet, + * let's not include it yet */ +#if 0 + if (FL_KICKSTART(flags)) { + 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]); + } + } + } +#endif + + if (num == -1 ) { + kbds = alloca(sizeof(*kbds) * (hdr.numEntries + 1)); + for (i = 0; i < hdr.numEntries; i++) { + kbds[i] = infoTable[i].name; + } + + kbds[i] = NULL; + qsort(kbds, i, sizeof(*kbds), simpleStringCmp); + + for (i = 0; i < hdr.numEntries; i++) + if (!strcmp(kbds[i], defkbd)) + num = i; + + rc = newtWinMenu(_("Keyboard Type"), + _("What type of keyboard do you have?"), + 40, 5, 5, 8, kbds, &num, _("OK"), _("Back"), NULL); + if (rc == 2) return LOADER_BACK; + + /* num needs to index the right keyboard infoTable */ + for (i = 0; i < hdr.numEntries; i++) + if (!strcmp(kbds[num], infoTable[i].name)) break; + num = i; + } + + rc = 0; + + for (i = 0; i < num; i++) { + if (gunzip_read(f, buf, infoTable[i].size) != infoTable[i].size) { + logMessage("error reading %d bytes from file: %s", + infoTable[i].size, strerror(errno)); + gunzip_close(f); + rc = LOADER_ERROR; + } + } + + if (!rc) rc = loadKeymap(f); + + gunzip_close(f); + + if (keymap) *keymap = strdup(infoTable[num].name); + +#ifdef __sparc__ + if (kbdtypep) *kbdtypep = (kbdtype == KBDTYPE_SUN) ? "sun" : "pc"; +#endif + + return rc; +} |