#include #include #include #include #include #include #include #include #include #include #include #include #include "cpio.h" #include "install.h" #include "kickstart.h" #include "lang.h" #include "log.h" #include "intl.h" extern int testing; struct aString { unsigned int hash; short length; char * str; } ; struct aString * strings = NULL; int numStrings = 0, allocedStrings = 0; static int loadFont(char * font); static int aStringCmp(const void * a, const void * b) { const struct aString * first = a; const struct aString * second = b; if (first->hash < second->hash) return -1; else if (first->hash == second->hash) return 0; return 1; } char * translateString(char * str) { unsigned int sum = 0, xor = 0; int len = 0; char * chptr; struct aString * match; struct aString key; for (chptr = str; *chptr; chptr++) { sum += *chptr; xor ^= *chptr; len++; } key.hash = (sum << 16) | ((xor & 0xFF) << 8) | (len & 0xFF); match = bsearch(&key, strings, numStrings, sizeof(*strings), aStringCmp); if (!match) return str; return match->str; } struct langInfo { char * lang, * key, * font, * map, * lc_all; } ; /* FONT LIST STARTS */ static const struct langInfo languages[] = { { "English", "en", NULL, NULL, "en_US" }, { "French", "fr", "lat0-sun16", "iso15", "fr_FR" }, { "German", "de", "lat0-sun16", "iso15", "de_DE" }, { "Hungarian", "hu", "lat2-sun16", "iso02", "hu_HU" }, { "Icelandic", "is", "lat0-sun16", "iso15", "is_IS" }, { "Italian", "it", "lat0-sun16", "iso15", "it_IT" }, { "Norwegian", "no", "lat0-sun16", "iso15", "no_NO" }, { "Romanian", "ro", "lat2-sun16", "iso02", "ro_RO" }, { "Slovak", "sk", "lat2-sun16", "iso02", "sk_SK" }, { "Russian", "ru", "Cyr_a8x16", "koi2alt", "ru_SU" }, { "Ukrainian", "uk_UA", "RUSCII_8x16", "koi2alt", "uk_UA" }, }; /* FONT LIST ENDS */ const int numLanguages = sizeof(languages) / sizeof(struct langInfo); int chooseLanguage(void) { int choice = 0; char ** langs; int i; int ksargc; char ** ksargv; if (strings) { free(strings), strings = NULL; numStrings = allocedStrings = 0; } if (kickstart && !ksGetCommand(KS_CMD_LANG, NULL, &ksargc, &ksargv)) { if (ksargc < 2) { logMessage("no argument passed to keyboard kickstart command"); } else { for (choice = 0; choice < numLanguages; choice++) if (!strcmp(languages[choice].key, ksargv[1])) break; if (choice == numLanguages) { logMessage("unknown language %s", ksargv[1]); } else if (!choice) { return INST_OKAY; } else { setenv("LANG", languages[choice].key, 1); setenv("LC_ALL", languages[choice].lc_all, 1); setenv("LINGUAS", languages[choice].key, 1); setDefaultLanguage(1); return INST_OKAY; } } } langs = alloca(sizeof(*langs) * (numLanguages + 1)); for (i = 0; i < numLanguages; i++) langs[i] = languages[i].lang; langs[i] = NULL; if (getenv("LANG")) { for (choice = 0; choice < numLanguages; choice++) if (!strcmp(languages[choice].key, getenv("LANG"))) break; if (choice == numLanguages) choice = 0; } /*loadFont("default8x16");*/ newtWinMenu(_("Choose a Language"), _("What language should be used " "during the installation process?"), 40, 5, 5, 8, langs, &choice, _("Ok"), NULL); if (!choice) { /* stick with the default (English) */ unsetenv("LANG"); unsetenv("LC_ALL"); unsetenv("LINGUAS"); return 0; } setenv("LANG", languages[choice].key, 1); setenv("LC_ALL", languages[choice].lc_all, 1); setenv("LINGUAS", languages[choice].key, 1); setDefaultLanguage(1); if (languages[choice].font) loadFont(languages[choice].font); return 0; } void setDefaultLanguage(int stage) { while (stage) { loadLanguageStage(stage, NULL); stage--; } } void loadLanguageStage(int which, char * file) { char filename[200]; FD_t stream; int fd, hash, rc; char * key = getenv("LANG"); if (!key || !strcmp(key, "en")) { if (strings) { free(strings), strings = NULL; numStrings = allocedStrings = 0; } return; } if (!file) { file = filename; if (testing) sprintf(filename, "install%d.tr", which); else sprintf(filename, "/etc/install%d.tr", which); } stream = fdOpen(file, O_RDONLY, 0644); if (fdFileno(stream) < 0) { newtWinMessage("Error", "Ok", "Cannot open %s: %s. Installation will " "proceed in English.", file, strerror(errno)); return ; } sprintf(filename, "%s%d.tr", key, which); rc = installCpioFile(stream, filename, "/tmp/translation", 1); fdClose(stream); if (rc || access("/tmp/translation", R_OK)) { newtWinMessage("Error", "Ok", "Cannot get translation file %s.\n", filename); return; } fd = open("/tmp/translation", O_RDONLY); if (fd < 0) { newtWinMessage("Error", "Ok", "Failed to open /tmp/translation: %s\n", strerror(errno)); return; } while (read(fd, &hash, 4) == 4) { if (allocedStrings == numStrings) { allocedStrings += 10; strings = realloc(strings, sizeof(*strings) * allocedStrings); } strings[numStrings].hash = ntohl(hash); read(fd, &strings[numStrings].length, 2); strings[numStrings].length = ntohs(strings[numStrings].length); strings[numStrings].str = malloc(strings[numStrings].length + 1); read(fd, strings[numStrings].str, strings[numStrings].length); strings[numStrings].str[strings[numStrings].length] = '\0'; numStrings++; } close(fd); unlink("/tmp/translation"); qsort(strings, numStrings, sizeof(*strings), aStringCmp); } static int loadFont(char * fontFile) { char font[8192]; unsigned short map[E_TABSZ]; struct unimapdesc d; struct unimapinit u; struct unipair desc[2048]; int fd; FD_t stream; int rc; if (!testing) { stream = fdOpen("/etc/fonts.cgz", O_RDONLY, 0644); if (fdFileno(stream) < 0) { newtWinMessage("Error", "Ok", "Cannot open fonts: %s", strerror(errno)); return INST_ERROR; } rc = installCpioFile(stream, fontFile, "/tmp/font", 1); fdClose(stream); if (rc || access("/tmp/font", R_OK)) { return INST_ERROR; } fd = open("/tmp/font", O_RDONLY); read(fd, font, sizeof(font)); read(fd, map, sizeof(map)); read(fd, &d.entry_ct, sizeof(d.entry_ct)); d.entries = desc; read(fd, desc, d.entry_ct * sizeof(desc[0])); close(fd); if (ioctl(1, PIO_FONT, font)) logMessage("PIO_FONT failed: %s", strerror(errno)); if (ioctl(1, PIO_UNIMAPCLR, &u)) logMessage("PIO_UNIMAPCLR failed: %s", strerror(errno)); if (ioctl(1, PIO_UNIMAP, &d)) logMessage("PIO_UNIMAP failed: %s", strerror(errno)); if (ioctl(1, PIO_UNISCRNMAP, map)) logMessage("PIO_UNISCRNMAP failed: %s", strerror(errno)); fprintf(stderr, "\033(K"); } return 0; } int writeLangInfo(char * rootPath) { char * lang = getenv("LANG"); int i; FILE * f; char * srcpath; char * path; if (testing || !lang) return 1; path = alloca(strlen(rootPath) + 40); sprintf(path, "%s/etc/sysconfig/i18n", rootPath); f = fopen(path, "w"); fprintf(f, "LANG=%s\n", lang); fprintf(f, "LINGUAS=%s\n", lang); for (i = 0; i < numLanguages; i++) if (!strcmp(languages[i].key, lang)) break; if (i < numLanguages && languages[i].lc_all) { fprintf(f, "LC_ALL=%s\n", languages[i].lc_all); } if (i < numLanguages && languages[i].font) { fprintf(f, "SYSFONT=%s\nSYSFONTACM=%s\n", languages[i].font, languages[i].map); } fclose(f); /* copy font file */ if (i < numLanguages && languages[i].font) { sprintf(path,"%s/etc/sysconfig/console/",rootPath); srcpath = alloca(strlen(path)+2*strlen(rootPath)+strlen(languages[i].font) + 80); sprintf(srcpath, "%s/bin/cp -f %s/usr/lib/kbd/consolefonts/%s.psf.gz %s", rootPath, rootPath, languages[i].font, path); system(srcpath); sprintf(srcpath, "%s/bin/cp -f %s/usr/lib/kbd/consoletrans/%s* %s", rootPath, rootPath, languages[i].map, path); system(srcpath); } return 0; }