home *** CD-ROM | disk | FTP | other *** search
- /**
- * File:
- * modules/GfxMenu.ycp
- *
- * Module:
- * Bootloader installation and configuration
- *
- * Summary:
- * Routines to maintain translations in the graphical bootloader menu
- *
- * Authors:
- * Jiri Srain <jsrain@suse.cz>
- * Olaf Dabrunz <od@suse.de>
- *
- * $Id: GfxMenu.ycp 33445 2006-10-16 22:33:57Z odabrunz $
- *
- */
-
- {
- module "GfxMenu";
-
- textdomain "bootloader";
-
- import "Mode";
-
- /**
- * Replace every match of given regular expression in a string with a
- * replacement string
- *
- * e.g. ReplaceRegexMatch( "abcdef12ef34gh000", "[0-9]+", "_A_" ) -> "abcdef_A_ef_A_gh_A_"
- *
- * @param input string that may contain substrings matching regex
- * @param regex regular expression to search for, must not contain brackets
- * @param repl string that replaces every substring matching the regex
- * @return string that has matches replaced
- */
- global define string ReplaceRegexMatch(string input, string regex, string repl) ``{
- if(input == nil || size(input) < 1) return "";
- string rest = input;
- string output = "";
- if( regexpmatch( rest, regex ) )
- {
- list p = regexppos( rest, regex );
- do
- {
- output = output +
- substring( rest, 0, p[0]:0 ) +
- repl;
- rest = substring( rest, p[0]:0+p[1]:0 );
- p = regexppos( rest, regex );
- }
- while( size(p)>0 );
- }
- return output + rest;
- }
-
- /**
- * Create translated name of a section
- * @param orig string original section name
- * @param loader string bootloader type
- * @return translated section name
- */
- global define string translateSectionTitle (string orig, string loader)
- ``{
- //
- // FIXME: handling of bootloader-specific restrictions should be done
- // in perl-Bootloader
- //
- map trans = $[
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "linux" : _("Linux"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "failsafe" : _("Failsafe"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "floppy" : _("Floppy"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "hard disk" : _("Hard Disk"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "memtest86" : _("Memory Test"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "original MBR" : _("MBR before Installation"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "previous" : _("Previous Kernel"),
- // entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space
- // are allowed, otherwise translartion won't be used
- // try to keep short, may be shortened due to bootloader limitations
- "Vendor diagnostics" : _("Vendor Diagnostics"),
- ];
- map not_trans = $[
- "linux" : "Linux",
- "failsafe" : "Failsafe",
- "floppy" : "Floppy",
- "hard disk" : "Hard Disk",
- "memtest86" : "Memory Test",
- "original MBR" : "MBR before Installation",
- "windows" : "Windows",
- "xen" : "XEN",
- ];
- string translated = trans[orig]:"\n"; // not allowed character
- // not_translated version will be used
- string filtered = filterchars (translated, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 _");
- if (size (filtered) != size (translated))
- {
- y2warning ("Incorrect translation %1 -> %2", orig, translated);
- return not_trans[orig]:orig;
- }
- if (loader != "grub")
- {
- // FIXME / FEATURE: At least for IA64, there is a two level boot
- // hierarchy (efibootmgr, elilo): the first level boot menu can be
- // used to select a partition (i.e. an installation), the second
- // level can be used to select a kernel/commandline set.
- // This may become an alternative setup for grub in the future
- // (requiring a separate menu.lst on an extra partition for the
- // first level, along with the changes in several parts of the
- // BootGRUB code for this).
- // AI: rw/od should discuss this with the grub maintainer and
- // create a feature for this.
- //
- // ATM, this is only available for IA64.
- // Thus, for "elilo", the second level string should remain
- // "linux", the product name already appears in the efi menu.
- if (loader != "elilo" && orig == "linux")
- {
- import "Product";
- string product = Product::short_name;
- string prod_filtered = filterchars (product, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 _.");
- if (product == prod_filtered && product != " ")
- {
- filtered = prod_filtered;
- }
- }
- y2milestone ("adapting section title: %1", filtered);
- // label tag for lilo.conf has a restricted valid character set and
- // limited allowed string length
- string cutoff = "";
-
- // Limit length to 11 characters, but keep it "nice"
- // 1. cut off linux- prefix if found
- if (size(filtered) > 11) {
- cutoff = regexpsub (filtered, "^[Ll][Ii][Nn][Uu][Xx]-", "");
- if (cutoff != nil)
- filtered = cutoff;
- }
-
- while (size(filtered) > 11) {
- // 2. cut off last word, break if no more found
- cutoff = regexpsub (filtered, "^(.*) [^ ]*$", "\\1");
- y2milestone ("cutoff is: %1", cutoff);
- if (cutoff == nil || size(cutoff) == size(filtered))
- break;
- filtered = cutoff;
- }
- y2milestone ("section title without excess words: %1", filtered);
-
- // 3. last resort: cutoff excess characters
- filtered = substring (filtered, 0, 11);
- y2milestone ("section title limited to 11 chars: %1", filtered);
-
- // 4. convert not allowed chars to "_"
- // (NOTE: this converts according to lilo requirements, ATM we do
- // not allow ".-" above already; so ATM this converts only " ")
- filtered = ReplaceRegexMatch (filtered, "[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.-]", "_");
- y2milestone ("section title: filtered unallowed characters: %1", filtered);
- }
- else if (contains (["linux", "failsafe", "previous", "xen"], orig)
- && ! Mode::test ())
- {
- /* for bootloaders that support long section names, like grub: */
- import "Product";
- string product = Product::name;
- string prod_filtered = filterchars (product, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 _.");
- if (product == prod_filtered && product != " ")
- {
- if (orig == "linux")
- {
- filtered = prod_filtered;
- }
- else
- {
- filtered = sformat ("%1 -- %2", filtered, prod_filtered);
- }
- }
- }
- return filtered;
- }
-
- /**
- * Get translated section names, including diacritics
- * @param loader string bootloader type
- * @return a map section names translations
- */
- global define map<string,string> getTranslationsToDiacritics (string loader) ``{
- map<string,string> trans = $[
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "linux" : _("_Linux"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "failsafe" : _("_Failsafe"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "floppy" : _("_Floppy"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "hard disk" : _("_Hard Disk"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "memtest86" : _("_Memory Test"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "original MBR" : _("_MBR before Installation"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "previous" : _("_Previous Kernel"),
- // entry of bootloader menu - only ISO 8859-1, -2 and -15 characters
- // are allowed. Always remove the leading '_', its just to
- // be able to have translations with and without diacritics
- // please use diacritics here
- "Vendor diagnostics" : _("_Vendor Diagnostics"),
- "xen" : "XEN",
- ];
- /* trans = filter (string k, string v, trans, {
- if (substring (v, 0, 1) == "_")
- {
- y2warning ("Translation %1 contains leading underscore", v);
- return false;
- }
- return true;
- });*/
- trans = mapmap (string k, string v, trans, {
- if (substring (v, 0, 1) == "_")
- v = substring (v, 1);
- return $[ k : v ];
- });
- map<string,string> ret = mapmap (string k, string v, trans, {
- string il1 = translateSectionTitle (k, loader);
- if (contains (["linux", "failsafe", "previous", "xen"], k) && ! Mode::test ())
- {
- import "Product";
- string product = Product::name;
- if (product != " ")
- {
- if (k == "linux")
- {
- v = product;
- }
- else
- {
- v = sformat ("%1 (%2)", product, v);
- }
- }
- }
- return $[il1 : v];
- });
- return ret;
- }
-
- /**
- * Update graphical bootloader to contain translations for section labels in
- * the currently selected installation language (set in
- * /etc/sysconfig/language, RC_LANG)
- * And make the selected installation language default
- * @param loader string bootloader type
- * @return boolean true on success
- */
- global define boolean UpdateGfxMenuContents (string loader) {
- y2milestone ("Updating GFX boot menu");
- // if the boot menu does not exist, return without updating it
- if (SCR::Read (.target.size, "/boot/message") == -1)
- return true;
- if (SCR::Read (.target.size, "/etc/sysconfig/bootsplash") == -1)
- return true;
-
- // get a list containing the system default language and the installed languages
- // get the current language
- string main_lang = (string)SCR::Read (.sysconfig.language.RC_LANG);
- string langs = (string)
- SCR::Read (.sysconfig.language.INSTALLED_LANGUAGES);
- if (langs == nil)
- langs = "";
- list<string> languages = splitstring (langs, ",");
- languages = prepend (languages, main_lang);
- languages = filter (string l, languages, {return l != nil;});
- // if no languages are installed and no main language is defined, we can do
- // nothing: simply return
- if (size (languages) == 0)
- return true;
-
- // if no boot theme is defined, we cannot create the GfxMenu: just leave
- string boot_theme = (string)SCR::Read (.sysconfig.bootsplash.THEME);
- if (boot_theme == nil)
- return true;
-
-
- // in the list of the system default language and the installed languages
- // find the subset that is supported by either a help text or a translation
- // file (for the GUI messages) or both
- // results:
- // selected -- list of supported languages (both long form (de_DE) and short form (de))
- // lang_params -- string of supported languages (both long form (de_DE) and short form (de))
-
- // get names of available languages
- string data_dir = sformat ("/etc/bootsplash/themes/%1/bootloader",
- boot_theme);
- list<string> files = (list<string>)SCR::Read (.target.dir, data_dir);
- list<string> helps = filter (string f, files, {
- return regexpmatch (f, "\\.hlp$");
- });
- list<string> texts = filter (string f, files, {
- return regexpmatch (f, "\\.tr$");
- });
- helps = maplist (string h, helps, ``(substring (h, 0, 2)));
- texts = maplist (string t, texts, ``(substring (t, 0, 2)));
- y2milestone ("Texts available for %1", sort (texts));
- y2milestone ("Helps available for %1", sort (helps));
-
- string tmpdir = (string)SCR::Read (.target.tmpdir);
- string lang_params = "";
-
- list<string> selected = [];
- foreach (string lang, languages, {
- list<string> l = splitstring (lang, ".");
- lang = l[0]:"";
- y2milestone ("Selected language for booting menu: %1", lang);
- l = splitstring (lang, "_");
- string lang_short = l[0]:"";
- // check if lang is supported by a help text and/or a GUI message
- // translation file
- if (! (contains (helps, lang_short) || contains (texts, lang_short)))
- {
- y2milestone ("Language %1 is not supported by gfxmenu", lang_short);
- }
- else if (! (contains (selected, lang)
- || contains (selected, lang_short)))
- {
- lang_params = sformat ("%1 %2 %3", lang_params, lang, lang_short);
- selected = add (selected, lang);
- selected = add (selected, lang_short);
- }
- });
-
- // create translation map (in temp file) for the currently active language
- // for gettext (AFAICT), i.e. whatever is found in LANG or LC_MESSAGES --
- // this should be RC_LANG
- string trans_file = sformat ("%1/boot_translations", tmpdir);
- map<string,string> trans_map = getTranslationsToDiacritics (loader);
- list<string> trans_list = maplist (string k, string v, trans_map, {
- return sformat ("%1\n%2", k, v);
- });
- string trans_str = mergestring (trans_list, "\n");
- trans_str = trans_str + "\n";
- SCR::Write (.target.string, trans_file, trans_str);
- if (lang_params == "")
- lang_params = "en_EN en";
-
- // update the boot message (/boot/message cpio archive) with menu entry
- // translation file (trans_file) and translation files for help texts and
- // UI texts
- // - currently (2006/09) update_gfxmenu includes the hlp and tr files only
- // for the first language (e.g. "de_DE de") from lang_params, the others
- // are ignored
- // - tr and hlp files that match the long language name ("de_DE") are
- // preferred over files that contain only the short language name
- // - English ("en") is always included in the list of selectable
- // languages, and the English tr and hlp files are never removed from
- // the message archive
- string command = sformat (
- "/usr/lib/YaST2/bin/update_gfxmenu %1 %2 %3 %4",
- tmpdir, data_dir, trans_file, lang_params);
-
- y2milestone ("Running command %1", command);
- map ret = (map)SCR::Execute (.target.bash_output, command);
- y2milestone ("GFXMenu update result: %1", ret);
- return ret["exit"]:0 == 0;
- }
-
- /**
- * Updates GFX menu without requiring any information, reads loader type
- * from sysconfig, calls /sbin/lilo if LILO is being used directly
- * @return boolean true on success
- */
- global boolean Update() {
- string loader = (string)SCR::Read (.sysconfig.bootloader.LOADER_TYPE);
- if (! UpdateGfxMenuContents (loader))
- return false;
-
- if (loader == "lilo")
- {
- map out = (map)SCR::Execute (.target.bash_output, "/sbin/lilo");
- if (out["exit"]:0 != 0)
- {
- y2error ("Output of /sbin/lilo: %1", out);
- return false;
- }
- }
- return true;
- }
-
-
-
-
-
-
-
-
-
-
- } //end of module
-