home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
modules
/
GfxMenu.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
17KB
|
438 lines
/**
* 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