#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" 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; } ; /* FONT LIST STARTS */ static const struct langInfo languages[] = { { "English", "en", NULL }, { "Czech", "cz", "lat2-16" }, { "French", "fr", "lat1-16" }, { "German", "de", "lat1-16" }, { "Norwegian", "no", "lat1-16" }, { "Redneck", "en_RN", NULL }, { "Romanian", "ro", "lat2-16" }, { "Turkish", "tr", "latin5-16" } , }; /* FONT LIST ENDS */ const 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("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("LINGUAS"); return 0; } setenv("LANG", languages[choice].key, 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]; gzFile 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 = gzopen(file, "r"); if (!stream) { 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); gzclose(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]; char map[E_TABSZ]; int fd; gzFile stream; int rc; if (!testing) { stream = gzopen("/etc/fonts.cgz", "r"); if (!stream) { newtWinMessage("Error", "Ok", "Cannot open fonts: %s", strerror(errno)); return INST_ERROR; } rc = installCpioFile(stream, fontFile, "/tmp/font", 1); gzclose(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)); close(fd); if (ioctl(1, PIO_FONT, font)) logMessage("PIO_FONT failed: %s", strerror(errno)); if (ioctl(1, PIO_SCRNMAP, map)) logMessage("PIO_SCRNMAP failed: %s", strerror(errno)); } if (!strcmp(fontFile, "lat1-16") || !strcmp(fontFile, "lat2-16")) { setenv("TERM", "linux-lat", 1); } else { setenv("TERM", "linux", 1); } return 0; } int writeLangInfo(void) { char * lang = getenv("LANG"); int i; FILE * f; if (testing || !lang) return 1; f = fopen("/mnt/etc/sysconfig/i18n", "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].font) { fprintf(f, "SYSFONT=%s\n", languages[i].font); } if (i < numLanguages && languages[i].font && (!strcmp(languages[i].font, "lat1-16") || !strcmp(languages[i].font, "lat2-16"))) { fprintf(f, "SYSTERM=linux-lat\n"); } fclose(f); return 0; }