summaryrefslogtreecommitdiffstats
path: root/loader/kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'loader/kbd.c')
-rw-r--r--loader/kbd.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/loader/kbd.c b/loader/kbd.c
new file mode 100644
index 000000000..94b68583f
--- /dev/null
+++ b/loader/kbd.c
@@ -0,0 +1,187 @@
+/*
+ * kbd.c - keyboard handling
+ *
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s): Erik Troan <ewt@redhat.com>
+ * Matt Wilson <msw@redhat.com>
+ * Michael Fulbright <msf@redhat.com>
+ * Jeremy Katz <katzj@redhat.com>
+ */
+
+#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"
+
+/* boot flags */
+extern uint64_t flags;
+
+int chooseKeyboard(struct loaderData_s * loaderData, char ** kbdtypep) {
+ 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 = loaderData->kbd ? loaderData->kbd : NULL;
+ char *lang;
+
+#if defined(__s390__) || defined(__s390x__)
+ return LOADER_NOOP;
+#endif
+
+ if (FL_SERIAL (flags) || FL_VIRTPCONSOLE(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);
+
+ lang = getenv("LANG");
+ if (!lang)
+ lang = loaderData->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(INFO, "%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;
+ }
+
+ 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, "error reading %d bytes from file: %m",
+ infoTable[i].size);
+ gunzip_close(f);
+ rc = LOADER_ERROR;
+ }
+ }
+
+ if (!rc) rc = loadKeymap(f);
+
+ /* normalize the error condition */
+ /* MSWFIXME - do we want to warn the user that setting the
+ keyboard didn't work?
+ */
+ if (rc != 0)
+ rc = LOADER_ERROR;
+ else
+ gunzip_close(f);
+
+ loaderData->kbd = strdup(infoTable[num].name);
+
+#ifdef __sparc__
+ if (kbdtypep) *kbdtypep = (kbdtype == KBDTYPE_SUN) ? "sun" : "pc";
+#endif
+
+ return rc;
+}
+
+void setKickstartKeyboard(struct loaderData_s * loaderData, int argc,
+ char ** argv) {
+ if (argc < 2) {
+ logMessage(ERROR, "no argument passed to keyboard kickstart command");
+ return;
+ }
+
+ loaderData->kbd = argv[1];
+ loaderData->kbd_set = 1;
+}