home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / kbd.c < prev    next >
C/C++ Source or Header  |  1997-10-09  |  6KB  |  265 lines

  1. #include <alloca.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <sys/ioctl.h>
  5. #include <linux/keyboard.h>
  6. #include <linux/kd.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <zlib.h>
  11.  
  12. #include "install.h"
  13. #include "kbd.h"
  14. #include "kickstart.h"
  15. #include "log.h"
  16. #include "newt.h"
  17. #include "windows.h"
  18.  
  19. /* the file pointer must be at the beginning of the section already! */
  20. static int loadKeymap(gzFile stream) {
  21.     int console;
  22.     int kmap, key;
  23.     struct kbentry entry;
  24.     int keymaps[MAX_NR_KEYMAPS];
  25.     int count = 0;
  26.     int magic;
  27.     short keymap[NR_KEYS];
  28.  
  29.     if (gzread(stream, &magic, sizeof(magic)) != sizeof(magic)) {
  30.     logMessage("failed to read kmap magic: %s", strerror(errno));
  31.     return INST_ERROR;
  32.     }
  33.  
  34.     if (magic != KMAP_MAGIC) {
  35.     logMessage("bad magic for keymap!");
  36.     return INST_ERROR;
  37.     }
  38.  
  39.     if (gzread(stream, keymaps, sizeof(keymaps)) != sizeof(keymaps)) {
  40.     logMessage("failed to read keymap header: %s", strerror(errno));
  41.     return INST_ERROR;
  42.     }
  43.  
  44.  
  45.     console = open("/dev/console", O_RDWR);
  46.     if (console < 0) {
  47.     logMessage("failed to open /dev/console: %s", strerror(errno));
  48.     return INST_ERROR;
  49.     }
  50.  
  51.     for (kmap = 0; kmap < MAX_NR_KEYMAPS; kmap++) {
  52.     if (!keymaps[kmap]) continue;
  53.  
  54.     if (gzread(stream, keymap, sizeof(keymap)) != sizeof(keymap)) {
  55.         logMessage("failed to read keymap data: %s", strerror(errno));
  56.         close(console);
  57.         return INST_ERROR;
  58.     }
  59.  
  60.     count++;
  61.     for (key = 0; key < NR_KEYS; key++) {
  62.         entry.kb_index = key;
  63.         entry.kb_table = kmap;
  64.         entry.kb_value = keymap[key];
  65.         if (KTYP(entry.kb_value) != KT_SPEC) {
  66.         if (ioctl(console, KDSKBENT, &entry)) {
  67.             close(console);
  68.             logMessage("keymap ioctl failed: %s", strerror(errno));
  69.         }
  70.         }
  71.     }
  72.     }
  73.  
  74.     logMessage("loaded %d keymap tables", count);
  75.  
  76.     close(console);
  77.  
  78.     return 0;
  79. }
  80.  
  81. int setupKeyboard(char ** keymap) {
  82.     newtComponent form, okay, listbox, answer;
  83.     int num = -1;
  84.     int rc;
  85.     gzFile f;
  86.     struct kmapHeader hdr;
  87.     struct kmapInfo * infoTable;
  88.     char ** argv;
  89.     int argc;
  90.     char buf[16384];             /* I hope this is big enough */
  91.     int i;
  92.  
  93.     if (testing) return 0;
  94.  
  95.     f = gzopen("/etc/keymaps.gz", "r");
  96.     if (!f) {
  97.     errorWindow("cannot open /etc/keymaps.gz: %s");
  98.     return INST_ERROR;
  99.     }
  100.  
  101.     if (gzread(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
  102.     errorWindow("failed to read keymaps header: %s");
  103.     gzclose(f);
  104.     return INST_ERROR;
  105.     }
  106.  
  107.     logMessage("%d keymaps are available", hdr.numEntries);
  108.  
  109.     i = hdr.numEntries * sizeof(*infoTable);
  110.     infoTable = alloca(i);
  111.     if (gzread(f, infoTable, i) != i) {
  112.     errorWindow("failed to read keymap information: %s");
  113.     gzclose(f);
  114.     return INST_ERROR;
  115.     }
  116.  
  117.     if (kickstart) {
  118.     if (!ksGetCommand(KS_CMD_KEYBOARD, NULL, &argc, &argv)) {
  119.         if (argc < 2) {
  120.         logMessage("no argument passed to keyboard "
  121.                 "kickstart command");
  122.         } else {
  123.         for (i = 0; i < hdr.numEntries; i++) 
  124.             if (!strcmp(infoTable[i].name, argv[1])) break;
  125.         if (i < hdr.numEntries)
  126.             num = i;
  127.         else 
  128.             newtWinMessage("Kickstart Error", "Ok", "Bad keymap "
  129.                    "name %s passed to kickstart command.",
  130.                    argv[1]);
  131.         }
  132.     }
  133.     }
  134.  
  135.     if (num == -1 ) {
  136.     newtCenteredWindow(40, 16, "Keyboard Type");
  137.  
  138.     form = newtForm(NULL, NULL, 0);
  139.  
  140.     newtFormAddComponent(form, newtLabel(3, 1, 
  141.                     "What type of keyboard do you have?"));
  142.  
  143.     listbox = newtListbox(8, 3, 8, NEWT_LISTBOX_RETURNEXIT);
  144.  
  145.     for (i = 0; i < hdr.numEntries; i++) {
  146.         newtListboxAddEntry(listbox, infoTable[i].name, (void *) i);
  147.  
  148.         if (!strcmp(infoTable[i].name, "us")) 
  149.         newtListboxSetCurrent(listbox, i);
  150.     }
  151.  
  152.     okay = newtButton(18, 12, "Ok");
  153.  
  154.     newtFormAddComponents(form, listbox, okay, NULL);
  155.  
  156.     answer = newtRunForm(form);
  157.  
  158.     num = (int) newtListboxGetCurrent(listbox);
  159.  
  160.     newtFormDestroy(form);
  161.     newtPopWindow();
  162.     }
  163.  
  164.     rc = 0;
  165.  
  166.     logMessage("using keymap %s", infoTable[num].name);
  167.  
  168.     for (i = 0; i < num; i++) {
  169.     if (gzread(f, buf, infoTable[i].size) != infoTable[i].size) {
  170.         logMessage("error reading %d bytes from file: %s", 
  171.                 infoTable[i].size, strerror(errno));
  172.         gzclose(f);
  173.         rc = INST_ERROR;
  174.     }
  175.     }
  176.  
  177.     if (!rc) rc = loadKeymap(f);
  178.  
  179.     gzclose(f);
  180.  
  181.     writeKbdConfig("/tmp", infoTable[num].name);
  182.  
  183.     if (keymap) *keymap = strdup(infoTable[num].name);
  184.  
  185.     return rc;
  186. }
  187.  
  188. int writeKbdConfig(char * prefix, char * keymap) {
  189.     FILE * f;
  190.     char * filename;
  191.  
  192.     if (testing || !keymap) return 0;
  193.  
  194.     filename = alloca(strlen(prefix) + 20);
  195.     sprintf(filename, "%s/keyboard", prefix);
  196.  
  197.     f = fopen(filename, "w");
  198.     if (!f) {
  199.     errorWindow("failed to create keyboard configuration: %s");
  200.     return INST_ERROR;
  201.     }
  202.  
  203.     if (fprintf(f, "KEYTABLE=\"/usr/lib/kbd/keytables/%s.map\"\n", 
  204.             keymap) < 0) {
  205.     errorWindow("failed to write keyboard configuration: %s");
  206.     return INST_ERROR;
  207.     }
  208.  
  209.     fclose(f);
  210.  
  211.     return 0;
  212. }
  213.  
  214. int readKbdConfig(char * prefix, char ** keymap) {
  215.     FILE * f;
  216.     char * filename;
  217.     char buf[255];
  218.     char * chptr;
  219.  
  220.     *keymap = NULL;
  221.  
  222.     if (testing) return 0;
  223.  
  224.     filename = alloca(strlen(prefix) + 20);
  225.     sprintf(filename, "%s/keyboard", prefix);
  226.  
  227.     f = fopen(filename, "r");
  228.     if (!f) {
  229.     /* fail silently -- old bootdisks won't create this */
  230.     logMessage("failed to read keyboard configuration (proably ok)");
  231.     return 0;
  232.     }
  233.  
  234.     /* this is a bit braindead -- we can steal better parsing from
  235.        kbdconfig if we ever need it */
  236.     if (!fgets(buf, sizeof(buf) - 1, f)) {
  237.     errorWindow("empty keyboard configuration file");
  238.     fclose(f);
  239.     return INST_ERROR;
  240.     }
  241.  
  242.     fclose(f);
  243.  
  244.     if (strncmp("KEYTABLE=", buf, 9)) {
  245.     errorWindow("unrecognized entry in keyboard configuration file");
  246.     return INST_ERROR;
  247.     }
  248.  
  249.     chptr = buf + strlen(buf) - 1;
  250.     /* ignore the '\n' on the end */
  251.     *chptr-- = '\0';
  252.     if (*chptr == '"') 
  253.     *chptr-- = '\0';
  254.  
  255.     while (chptr > buf && *chptr != '.') chptr--;
  256.     if (*chptr == '.') *chptr-- = '\0';
  257.  
  258.     while (chptr > buf && *chptr != '/') chptr--;
  259.     if (*chptr == '/') chptr++;
  260.  
  261.     *keymap = strdup(chptr);
  262.  
  263.     return 0;
  264. }
  265.