home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / lang.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-13  |  7.3 KB  |  310 lines

  1. #include <alloca.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <netinet/in.h>
  5. #include <newt.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/kd.h>
  10. #include <sys/ioctl.h>
  11. #include <unistd.h>
  12. #include <zlib.h>
  13.  
  14. #include "cpio.h"
  15. #include "install.h"
  16. #include "kickstart.h"
  17. #include "lang.h"
  18. #include "log.h"
  19.  
  20. extern int testing;
  21.  
  22. struct aString {
  23.     unsigned int hash;
  24.     short length;
  25.     char * str;
  26. } ;
  27.  
  28. struct aString * strings = NULL;
  29. int numStrings = 0, allocedStrings = 0;
  30.  
  31. static int loadFont(char * font);
  32.  
  33. static int aStringCmp(const void * a, const void * b) {
  34.     const struct aString * first = a;
  35.     const struct aString * second = b;
  36.  
  37.     if (first->hash < second->hash)
  38.     return -1;
  39.     else if (first->hash == second->hash)
  40.     return 0;
  41.  
  42.     return 1;
  43. }
  44.  
  45. char * translateString(char * str) {
  46.     unsigned int sum = 0, xor = 0;
  47.     int len = 0;
  48.     char * chptr;
  49.     struct aString * match;
  50.     struct aString key;
  51.  
  52.     for (chptr = str; *chptr; chptr++) {
  53.     sum += *chptr;
  54.     xor ^= *chptr;
  55.     len++;
  56.     }
  57.  
  58.     key.hash = (sum << 16) | ((xor & 0xFF) << 8) | (len & 0xFF);
  59.  
  60.     match = bsearch(&key, strings, numStrings, sizeof(*strings), aStringCmp);
  61.     if (!match)
  62.     return str;
  63.  
  64.     return match->str;
  65. }
  66.  
  67. struct langInfo {
  68.     char * lang, * key, * font, * lc_all;
  69. } ;
  70.  
  71. /* FONT LIST STARTS */
  72. static const struct langInfo languages[] = {
  73.     { "English", "en", NULL, "en_US" },
  74.     { "Czech", "cs", "lat2-16", "cs_CZ" },
  75.     { "Danish", "da", "lat1-16", "da_DK" },
  76.     { "Finnish", "fi", "lat1-16", "fi_FI" },
  77.     { "French", "fr", "lat1-16", "fr_FR" },
  78.     { "German", "de", "lat1-16", "de_DE" },
  79.     { "Italian", "it", "lat1-16", "it_IT" },
  80.     { "Norwegian", "no", "lat1-16", "no_NO" },
  81.     { "Romanian", "ro", "lat2-16", "ro_RO" },
  82.     { "Serbian", "sr", "lat2-16", "sr_YU" },
  83.     { "Slovak", "sk", "lat2-16", "sk_SK" },
  84.     { "Swedish", "se", "lat1-16", "sv_SE" },
  85.     { "Turkish", "tr", "latin5-16", "tr_TR" } ,
  86. };
  87. /* FONT LIST ENDS */
  88. const int numLanguages = sizeof(languages) / sizeof(struct langInfo);
  89.  
  90. int chooseLanguage(void) {
  91.     int choice = 0;
  92.     char ** langs;
  93.     int i;
  94.     int ksargc;
  95.     char ** ksargv;
  96.  
  97.     if (strings) {
  98.     free(strings), strings = NULL;
  99.     numStrings = allocedStrings = 0;
  100.     }
  101.  
  102.     if (kickstart && !ksGetCommand(KS_CMD_LANG, NULL, &ksargc, &ksargv)) {
  103.     if (ksargc < 2) {
  104.         logMessage("no argument passed to keyboard kickstart command");
  105.     } else {
  106.         for (choice = 0; choice < numLanguages; choice++)
  107.         if (!strcmp(languages[choice].key, ksargv[1])) break;
  108.         if (choice == numLanguages) {
  109.         logMessage("unknown language %s", ksargv[1]);
  110.         } else if (!choice) {
  111.         return INST_OKAY;
  112.         } else {
  113.         setenv("LANG", languages[choice].key, 1);
  114.         setenv("LC_ALL", languages[choice].lc_all, 1);
  115.         setenv("LINGUAS", languages[choice].key, 1);
  116.         setDefaultLanguage(1);
  117.         return INST_OKAY;
  118.         }
  119.     }
  120.     }
  121.  
  122.     langs = alloca(sizeof(*langs) * (numLanguages + 1));
  123.     for (i = 0; i < numLanguages; i++)
  124.     langs[i] = languages[i].lang;
  125.  
  126.     langs[i] = NULL;
  127.  
  128.     if (getenv("LANG")) {
  129.     for (choice = 0; choice < numLanguages; choice++)
  130.         if (!strcmp(languages[choice].key, getenv("LANG"))) break;
  131.     if (choice == numLanguages) choice = 0;
  132.     }
  133.  
  134.     /*loadFont("default8x16");*/
  135.  
  136.     newtWinMenu("Choose a Language", "What language should be used "
  137.         "during the installation process?", 40, 5, 5, 8,
  138.         langs, &choice, "Ok", NULL);
  139.  
  140.     if (!choice) {
  141.     /* stick with the default (English) */
  142.     unsetenv("LANG");
  143.     unsetenv("LC_ALL");
  144.     unsetenv("LINGUAS");
  145.     return 0;
  146.     }
  147.  
  148.     setenv("LANG", languages[choice].key, 1);
  149.     setenv("LC_ALL", languages[choice].lc_all, 1);
  150.     setenv("LINGUAS", languages[choice].key, 1);
  151.     setDefaultLanguage(1);
  152.     if (languages[choice].font)
  153.     loadFont(languages[choice].font);
  154.  
  155.     return 0;
  156. }
  157.  
  158. void setDefaultLanguage(int stage) {
  159.     while (stage) {
  160.     loadLanguageStage(stage, NULL);
  161.     stage--;
  162.     }
  163. }
  164.  
  165. void loadLanguageStage(int which, char * file) {
  166.     char filename[200];
  167.     gzFile stream;
  168.     int fd, hash, rc;
  169.     char * key = getenv("LANG");
  170.  
  171.     if (!key || !strcmp(key, "en")) {
  172.     if (strings) {
  173.         free(strings), strings = NULL;
  174.         numStrings = allocedStrings = 0;
  175.     }
  176.     return;
  177.     }
  178.  
  179.     if (!file) {
  180.     file = filename;
  181.     if (testing)
  182.         sprintf(filename, "install%d.tr", which);
  183.     else
  184.         sprintf(filename, "/etc/install%d.tr", which);
  185.     }
  186.  
  187.     stream = gzopen(file, "r");
  188.  
  189.     if (!stream) {
  190.     newtWinMessage("Error", "Ok", "Cannot open %s: %s. Installation will "
  191.             "proceed in English.", file, strerror(errno));
  192.     return ;
  193.     }
  194.     
  195.     sprintf(filename, "%s%d.tr", key, which);
  196.  
  197.     rc = installCpioFile(stream, filename, "/tmp/translation", 1);
  198.     gzclose(stream);
  199.     if (rc || access("/tmp/translation", R_OK)) {
  200.     newtWinMessage("Error", "Ok", "Cannot get translation file %s.\n", 
  201.             filename);
  202.     return;
  203.     }
  204.     
  205.     fd = open("/tmp/translation", O_RDONLY);
  206.     if (fd < 0) {
  207.     newtWinMessage("Error", "Ok", "Failed to open /tmp/translation: %s\n", 
  208.             strerror(errno));
  209.     return;
  210.     }
  211.  
  212.     while (read(fd, &hash, 4) == 4) {
  213.     if (allocedStrings == numStrings) {
  214.         allocedStrings += 10;
  215.         strings = realloc(strings, sizeof(*strings) * allocedStrings);
  216.     }
  217.  
  218.     strings[numStrings].hash = ntohl(hash);
  219.     read(fd, &strings[numStrings].length, 2);
  220.     strings[numStrings].length = ntohs(strings[numStrings].length);
  221.     strings[numStrings].str = malloc(strings[numStrings].length + 1);
  222.     read(fd, strings[numStrings].str, strings[numStrings].length);
  223.     strings[numStrings].str[strings[numStrings].length] = '\0';
  224.     numStrings++;
  225.     }
  226.  
  227.     close(fd);
  228.     unlink("/tmp/translation");
  229.  
  230.     qsort(strings, numStrings, sizeof(*strings), aStringCmp);
  231. }
  232.  
  233. static int loadFont(char * fontFile) {
  234.     char font[8192];
  235.     char map[E_TABSZ];
  236.     int fd;
  237.     gzFile stream;
  238.     int rc;
  239.  
  240.     if (!testing) {
  241.     stream = gzopen("/etc/fonts.cgz", "r");
  242.     if (!stream) {
  243.         newtWinMessage("Error", "Ok", 
  244.             "Cannot open fonts: %s", strerror(errno));
  245.         return INST_ERROR;
  246.     }
  247.  
  248.     rc = installCpioFile(stream, fontFile, "/tmp/font", 1);
  249.     gzclose(stream);
  250.     if (rc || access("/tmp/font", R_OK)) {
  251.         return INST_ERROR;
  252.     }
  253.  
  254.     fd = open("/tmp/font", O_RDONLY);
  255.     read(fd, font, sizeof(font));
  256.     read(fd, map, sizeof(map));
  257.     close(fd);
  258.  
  259.     if (ioctl(1, PIO_FONT, font))
  260.         logMessage("PIO_FONT failed: %s", strerror(errno)); 
  261.  
  262.     if (ioctl(1, PIO_SCRNMAP, map))
  263.         logMessage("PIO_SCRNMAP failed: %s", strerror(errno)); 
  264.     }
  265.  
  266.     if (!strcmp(fontFile, "lat1-16") || !strcmp(fontFile, "lat2-16")) {
  267.     setenv("TERM", "linux-lat", 1);
  268.     } else {
  269.     setenv("TERM", "linux", 1);
  270.     }
  271.  
  272.     return 0;
  273. }
  274.  
  275. int writeLangInfo(char * rootPath) {
  276.     char * lang = getenv("LANG");
  277.     int i;
  278.     FILE * f;
  279.     char * path;
  280.  
  281.     if (testing || !lang) return 1;
  282.  
  283.     path = alloca(strlen(rootPath) + 40);
  284.     sprintf(path, "%s/etc/sysconfig/i18n", rootPath);
  285.     f = fopen(path, "w");
  286.     fprintf(f, "LANG=%s\n", lang);
  287.     fprintf(f, "LINGUAS=%s\n", lang);
  288.  
  289.     for (i = 0; i < numLanguages; i++)
  290.     if (!strcmp(languages[i].key, lang)) break;
  291.     
  292.     if (i < numLanguages && languages[i].lc_all) {
  293.     fprintf(f, "LC_ALL=%s\n", languages[i].lc_all);
  294.     }
  295.  
  296.     if (i < numLanguages && languages[i].font) {
  297.     fprintf(f, "SYSFONT=%s\n", languages[i].font);
  298.     }
  299.  
  300.     if (i < numLanguages && languages[i].font &&
  301.            (!strcmp(languages[i].font, "lat1-16") || 
  302.         !strcmp(languages[i].font, "lat2-16"))) {
  303.     fprintf(f, "SYSTERM=linux-lat\n");
  304.     }
  305.  
  306.     fclose(f);
  307.  
  308.     return 0;
  309. }
  310.