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