1. 多語言環(huán)境支持
為了在Linux下實(shí)現(xiàn)多語言支持,必須在定制安裝程序時(shí),引入與glibc和圖形環(huán)境兩者對(duì)應(yīng)的多語言環(huán)境支持。對(duì)于glibc環(huán)境而言,它是整個(gè) Linux中文化的基礎(chǔ),我們需要在/usr/share/locale目錄下保存Locale信息,在/usr/share/consolefonts 目錄下保存字體信息,在/usr/lib/gconv目錄下保存字符轉(zhuǎn)換模塊的信息。
對(duì)于X Windows環(huán)境,我們需要在/usr/X11R6/lib/X11/locale目錄下保存X Locale的配置,同時(shí)在/usr/X11R6/lib/X11/fonts目錄下保存正常顯示所需要的字體集。
在安裝程序啟動(dòng)之后,必須正確設(shè)置LC_*變量同時(shí)調(diào)用setlocale函數(shù)。為了能顯示中文,安裝程序還必須加載正確的中文字體。
1.1. 國(guó)際化的基本概念
國(guó)際化(Internationalization,簡(jiǎn)寫為I18N)是指軟件在設(shè)計(jì)結(jié)構(gòu)和機(jī)制上支持多語言的擴(kuò)展特性,其功能和代碼設(shè)計(jì)不針對(duì)某一特定語言和地域。Locale是ANSI C語言中最基本的支持國(guó)際化的標(biāo)志,對(duì)中文Linux來說,支持中文Locale是最基本的要求。
1.1.1. Locale環(huán)境
Locale的命名規(guī)則:<語言>_<地區(qū)名>.<字符編碼名稱>
對(duì)于zh_CN.GB2312而言,zh表示中文,CN表示大陸地區(qū),GB2312表示使用的字符集為GB2312。
Locale使用一組分類,用戶可以獨(dú)立的操縱每一組分類。用戶既能用設(shè)置環(huán)境變量的方法,也能使用setlocale設(shè)置它們。這些分類都保存在/usr/share/locale下。它們包含了:
LC_COLLATE
用于比較和排序。
LC_CTYPE
用于字符分類和字符串處理,控制所有字符的處理方式,包括字符編碼,字符是單字節(jié)還是多字節(jié),如何打印等。
LC_MONETORY
用于格式化貨幣單位。
LC_NUMERIC
用于格式化非貨幣的數(shù)字顯示。
LC_TIME
用于格式化時(shí)間和日期。
LC_MESSAGES
用于控制程序輸出時(shí)所使用的語言,主要是提示信息,錯(cuò)誤信息,狀態(tài)信息, 標(biāo)題,標(biāo)簽, 按鈕和菜單等。
LC_ALL
它不是環(huán)境變量,只是一個(gè)宏,可使用setlocale設(shè)置所有的LC_*環(huán)境變量。這個(gè)變量設(shè)置之后,可以廢除LC_*和LANG的設(shè)置值,使得這些變量的設(shè)置值與LC_ALL的值一致。
LANG
它的值用于指定上面環(huán)境變量沒有設(shè)置的所有變量值。如果指定了上面任何一個(gè)變量的值,則會(huì)廢除對(duì)應(yīng)的LANG值的缺省設(shè)置。
還可以包括其他的環(huán)境變量LC_ADDRESS,LC_IDENTIFICATION,LC_PAPER,LC_NAME,LC_TELEPHONE,LC_MEASUREMENT。
標(biāo)準(zhǔn)Locale:
"C"
這是標(biāo)準(zhǔn)的C Locale。它所指定的屬性和行為由ISO C標(biāo)準(zhǔn)所指定。它是程序啟動(dòng)時(shí)缺省使用Locale。
"POSIX"
這是標(biāo)準(zhǔn)的POSIX Locale。它是標(biāo)準(zhǔn)的C Locale的別名。
""
空名字是讓程序選擇當(dāng)前環(huán)境設(shè)置值。
設(shè)置一個(gè)中文環(huán)境需要正確的設(shè)置上述Locale變量,舉例來說,在使用zh_CN.GB2312環(huán)境時(shí),使用locale命令,所見到的系統(tǒng)環(huán)境為:
LANG="zh_CN.GB2312"
LC_CTYPE="zh_CN.GB2312"
LC_NUMERIC="zh_CN.GB2312"
LC_TIME="zh_CN.GB2312"
LC_COLLATE="zh_CN.GB2312"
LC_MONETARY="zh_CN.GB2312"
LC_MESSAGES="zh_CN.GB2312"
LC_PAPER="zh_CN.GB2312"
LC_NAME="zh_CN.GB2312"
LC_ADDRESS="zh_CN.GB2312"
LC_TELEPHONE="zh_CN.GB2312"
LC_MEASUREMENT="zh_CN.GB2312"
LC_IDENTIFICATION="zh_CN.GB2312"
LC_ALL=
1.1.2. 創(chuàng)建Locale環(huán)境
為了建立locale環(huán)境,我們必須具備下面的描述文件:
locale-data
這個(gè)文件定義了Locale環(huán)境(LC_*)的所有細(xì)節(jié),包括字符的分類與轉(zhuǎn)換,字符排序,區(qū)域顯示時(shí)間,貨幣顯示格式等等。通常是保存在系統(tǒng)的/usr/share/i18n/locales目錄下。
charmap
這個(gè)文件定義了Locale中所有字符與內(nèi)碼的對(duì)應(yīng)關(guān)系。通常是保存在系統(tǒng)的/usr/share/i18n/charmaps目錄下。
這兩個(gè)文件都是純文本文件,可以使用文本編輯器直接察看和修改。通過這兩個(gè)文件就可以生成對(duì)應(yīng)的locale環(huán)境。缺省條件下,生成的locale環(huán)境是以二進(jìn)制的形式保存在/usr/share/locale目錄下。把這兩個(gè)文本文件生成locale環(huán)境的工作是由localedef程序?qū)崿F(xiàn)的。舉例來說,生成zh_CN.GB2312的locale環(huán)境:
mkdir /home/usr/share/locale/zh_CN.gb2312
localedef -I zh_CN -f GB2312 zh_CN.GB2312 --prefix=/home
cd /home/usr/share/locale/
mv zh_CN.gb2312 zh_CN.GB2312
這幾條命令在/home目錄下,生成Locale環(huán)境zh_CN.GB2312。因?yàn)榘凑誔OSIX標(biāo)準(zhǔn),一個(gè)Locale的編碼名稱是大小寫無關(guān)的。雖然我們指定的是大寫的GB2312,但是glibc為了統(tǒng)一起見,它會(huì)生成一個(gè)小寫的編碼名稱。但是由于很多程序依賴于zh_CN.GB2312,因此對(duì)這個(gè)文件進(jìn)行了改名。
除了Locale環(huán)境之外,您還需要gconv文件。這一組文件是用來定義glibc的gconv系統(tǒng)在遇到GB2312編碼的字符時(shí),應(yīng)使用哪一個(gè)模塊來處理。gconv-modules文件描述了字符編碼和處理模塊文件對(duì)應(yīng)關(guān)系。例如,在/usr/lib/gconv/gonv-modules文件中,需要包含下列行:
alias GB2312// EUC-CN//
1.1.3. X Window系統(tǒng)的多語言環(huán)境
X Window系統(tǒng)的多語言環(huán)境是在系統(tǒng)底層libc的Locale架構(gòu)的基礎(chǔ)上建立起來的。X函數(shù)庫(kù)需要利用libc提供的函數(shù)來進(jìn)行字符之間的轉(zhuǎn)換。因此,為了使X Window應(yīng)用程序的Locale正確工作,您必須首先設(shè)置一個(gè)正確的libc Locale環(huán)境,同時(shí)正確設(shè)置LC_CTYPE這個(gè)類別。
指定了編碼方式并且將字符的辨識(shí)和轉(zhuǎn)換用libc的函數(shù)處理之后,X Window系統(tǒng)的多語言處理的主要問題就變?yōu)閳D形顯示和輸入了。在X系統(tǒng)下,多語言環(huán)境必須能做到多語言字符圖形化輸出和字符輸入。字符的圖形化輸出還要處理字型,這又與字型的設(shè)定方式有關(guān)。
與libc一樣,在X Window系統(tǒng)下也有關(guān)于Locale的設(shè)置部分,稱為X-Locale。XFree86系統(tǒng)都把它保留在 /usr/X11R6/lib/X11/locale目錄下。在這個(gè)目錄下的每個(gè)Locale都有一個(gè)目錄,存放各自的X-locale,一般這個(gè)文件的名字是XLC_LOCALE。這個(gè)文件里面包含了跟該區(qū)域編碼相關(guān)的設(shè)定,而文件中以#字號(hào)開頭的是注釋。以安裝程序上簡(jiǎn)體中文XLC_LOCALE的內(nèi)容為例:
XLC_FONTSET
# fs0 class (7 bit ASCII)
fs0 {
charset {
name ISO8859-1:GL
}
font {
primary ISO8859-1:GL
vertical_rotate all
}
}
# fs1 class
fs1 {
charset {
name GB2312.1980-0:GL
}
font {
primary GB2312.1980-0:GL
}
}
END XLC_FONTSET
以上內(nèi)容定義的是顯示Locale時(shí)使用的字符集。在多語言環(huán)境中,為了同時(shí)顯示中英文,系統(tǒng)往往需要多種字體。例如,上例中表示:在顯示簡(jiǎn)體中文時(shí)要使用兩種不同編碼的字體,其中一個(gè)是使用了GB2312編碼的中文字體,其字體名稱以GB2312.1980-0結(jié)束,另一個(gè)是ISO8859-1編碼的英文字體,其字體名稱以ISO8859-1結(jié)束。
XLC_LOCALE的下一部分定義了Locale中的字體在X系統(tǒng)中的處理方式:
XLC_XLOCALE
encoding_name zh.euc
mb_cur_max 2
state_depend_encoding False
wc_encoding_mask \x30000000
wc_shift_bits 7
cs0 {
side GL:Default
length 1
wc_encoding \x00000000
ct_encoding ISO8859-1:GL
}
cs1 {
side GR:Default
length 2
wc_encoding \x30000000
ct_encoding GB2312.1980-0:GL; GB2312.1980-0:GR
}
END XLC_XLOCALE
cs0定義的部分為iso8859-1編碼的英文字符,每個(gè)字符占用一個(gè)字節(jié)。cs1定義的部分為GB2312編碼的中文字符,每個(gè)字符占用兩個(gè)字節(jié),這兩個(gè)字節(jié)都必須用GB2312.1980-0的字體來表示。注意,對(duì)于上面的X設(shè)置,GB2312.1980-1類型的字體是無法正常顯示的,除非用戶修改X Locale。
除此之外,/usr/X11R6/lib/X11/locale還使用locale.dir和locale.alias文件定義可用X-Locale的名稱和位置。其中,locale.dir定義了每個(gè)X-Locale文件的位置以及實(shí)際的Locale名稱。locale.alias文件則定義了每個(gè) Locale可能的別名。
X Window 的字體存放在/usr/X11R6/lib/X11/fonts目錄下,一般使用PCF的字體。在將新的字體文件拷貝到此目錄之后,運(yùn)行
mkfontdir
由這條命令更新改目錄下的fonts.dir的內(nèi)容。例如,
fzs14.pcf.Z fzs14
helvR12_iso01.pcf.gz -adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1
上面兩行的信息是從字體文件中抽取出來的,比如,helvR12_iso01.pcf.gz文件中就包含iso8859-1編碼的文件。但是,字體文件 fzs14.pcf.Z就不包含類似的字體說明信息,因此我們還需要使用fonts.alias文件建立字體別名。
-hlc-song-medium-r-normal--14-140-75-75-c-140-gb2312.1980-0 fzs14
這樣在安裝程序使用下面的資源時(shí),X Window系統(tǒng)就知道要加載fzs14字體了。
style "font" {
fontset="-*-helvetica-*-r-normal-*-14-*-*-*-*-*-iso8859-1, -*-medium-*-14-*-*-*-*-*-*-gb2312.1980-0"
}
1.2. 安裝程序的國(guó)際化實(shí)現(xiàn)
自動(dòng)生成po文件
在安裝程序中,定義了兩個(gè)函數(shù)_()和__(),前者是對(duì)傳入的串進(jìn)行翻譯,后者是直接返回傳入的串,凡是要進(jìn)行多語言支持的串必須使用這兩個(gè)函數(shù)。它們兩者在安裝程序中的用法是不同的。前者是用于一些可以進(jìn)行重建的界面控件,并且它們的值一般作為局部變量出現(xiàn);而后者一般用于全局變量,為了讓這個(gè)串顯示多種語言,需要使用translate()函數(shù)進(jìn)行處理。使用這兩個(gè)函數(shù)的主要目的是可以很方便的使用xgettext程序自動(dòng)生成po文件。
xgettext只對(duì)c語言的源程序文件生效,因此在使用它之前必須先將perl源程序轉(zhuǎn)換為c程序,然后再運(yùn)行xgettext自動(dòng)提出需要進(jìn)行多語言處理的文本串。下面的程序段是po目錄下Makefile文件的一部分,它可以自動(dòng)生成空的po文件。
PMSFILES = $(wildcard *.pm)
PMSCFILES = $(PMSFILES:%=%_.c)
POFILES = $(shell ls *.po)
all: $(PMSCFILES) DrakX.pot
clean:
rm -f empty.po messages $(POFILES:%=%t) $(PMSCFILES)
verif:
perl -ne '/^\s*#/ or $$i += my @l = /\b__?\(/g; END { print "$$i\n" }' $(PMSFILES)
perl -ne '$$i += my @l = /\.c:/g; END { print "$$i\n" }' DrakX.pot
DrakX.pot: $(PMSFILES)
xgettext -F -n --keyword=_ --keyword=__ -o $@ $(PMSCFILES)
rm $(PMSCFILES)
$(PMSCFILES): %_.c: %
perl -pe 's|^(__?\()| $$1|; s|#([^+].*)|/*\1*\/|; s|$$|\\n\\|' $< > $@
處理po文件
在安裝程序中po文件并不進(jìn)行編譯。因?yàn)閜erl語言處理文本文件的能力非常強(qiáng),所以它直接作為文本文件形式存在。在調(diào)入po文件時(shí),perl根據(jù)msgid和msgstr的內(nèi)容生成一個(gè)hash結(jié)構(gòu),然后由此結(jié)構(gòu)進(jìn)行文本串的處理。
#- 此函數(shù)加載指定語言的po文件
sub load_po {
my ($lang) = @_;
my ($s, $from, $to, $state, $fuzzy);
#- 將$s中的內(nèi)容作為一個(gè)perl文件存在,在這個(gè)文件中生成一個(gè)巨大的hash結(jié)構(gòu)
#- 當(dāng)進(jìn)行多語言處理時(shí),根據(jù)這個(gè)hash結(jié)構(gòu)獲得翻譯的文本串。
$s .= "package po::I18N;\n";
$s .= "no strict;\n";
$s .= "\%{'$lang'} = (";
$f = "po/$lang.po";
local *F;
my $pid;
unless ($f && -e $f) {
… …
#- 如果文件不存在,則從壓縮包中取出此文件,并打開
}
local $_;
while (
/^msgstr/ and $state = 1;
/^msgid/ && !$fuzzy and $state = 2;
s/@/\\@/g;
if (/^(#|$)/ && $state != 3) {
$state = 3;
if (my @l = $to =~ /%(\d+)\$/g) {
$to =~ s/%(\d+)\$/%/g;
$to = qq([ "$to", ] . join(",", map { $_ - 1 } @l) . " ),";
} else {
$to = qq("$to");
}
#- 形成hash結(jié)構(gòu),msgid的內(nèi)容保存在$from中,msgstr的內(nèi)容保存在$to中
$s .= qq("$from" => $to,\n) if $from;
$from = $to = '';
}
$to .= (/"(.*)"/)[0] if $state == 1;
$from .= (/"(.*)"/)[0] if $state == 2;
$fuzzy = /^#, fuzzy/;
}
$s .= ");";
no strict "vars";
eval $s;
$pid and waitpid $pid, 0;
!$@;
}
文本串翻譯
#- 文本串的翻譯過程主要是訪問讀入po文件所形成的hash結(jié)構(gòu),由它的值返回翻譯后的文本串。
sub translate {
my ($s) = @_;
#- 如果Locale環(huán)境未設(shè)置,則設(shè)置環(huán)境為英語
my ($lang) = $ENV{LANGUAGE} || $ENV{LC_MESSAGES} || $ENV{LC_ALL} || $ENV{LANG} || 'en';
require lang;
foreach (split ':', $lang) {
#- 如果hash結(jié)構(gòu)未定義,則調(diào)入語言對(duì)應(yīng)的po文件
lang::load_po($_) unless defined $po::I18N::{$_};
#- 如果未能正確加載po文件或者待翻譯的串不存在,則返回源串$s。
if (%{$po::I18N::{$_}}) {
return if $s eq '_I18N_';
return ${$po::I18N::{$_}}{$s} || $s
}
}
$s;
}
l 設(shè)置Locale環(huán)境
設(shè)置Locale環(huán)境主要就是設(shè)置Locale變量的值。
#- [ 'English|United States', 'iso-8859-1', 'en', 'en_US:en' ]這個(gè)數(shù)組表示
#- 第一個(gè)元素是語言環(huán)境的文本描述。
#- 通過第二個(gè)元素的值查詢%charset結(jié)構(gòu),可以獲得對(duì)應(yīng)的字體。
#- 第三個(gè)元素是LANG變量的設(shè)置值。
#- 第四個(gè)元素是LANGUAGE變量的設(shè)置值。
my %languages = (
'en_US' => [ 'English|United States', 'iso-8859-1', 'en', 'en_US:en' ],
'zh_CN.GB2312' => [ 'Chinese|Simplified', 'gb2312', 'zh_CN.GB2312', 'zh_CN.GB2312:zh_CN.gb2312:zh_CN:zh' ]
);
my %charsets = (
"iso-8859-1" => [ "lat0-sun16", undef, "iso15",
"iso8859-1", "850", sub { std("iso8859-1", @_) } ],
"gb2312" => [ undef, undef, undef,
"gb2312", "936", "-*-*-*-*-*-*-*-*-*-*-*-*-gb2312.1980-1" ],
);
unless (-e "$ENV{SHARE_PATH}/locale/$languages{$lang}[2]") {
@ENV{qw(LANG LC_ALL LANGUAGE LINGUAS)} = ();
eval { commands::rm("-r", "$ENV{SHARE_PATH}/locale") };
eval {
#- 取出Locale環(huán)境
require packdrake;
my $packer = new packdrake("$ENV{SHARE_PATH}/locale.cz2");
$packer->extract_archive("$ENV{SHARE_PATH}/locale", "UTF-8", $languages{$lang}[2]);
};
}
#- 明確設(shè)置Locale的環(huán)境變量
$ENV{LC_NUMERIC} = "C";
$ENV{LC_TIME} = "C";
$ENV{LC_COLLATE} = "C";
$ENV{LC_MONETARY} = "C";
$ENV{LC_MESSAGES} = "C";
$ENV{LC_PAPER} = "C";
$ENV{LC_NAME} = "C";
$ENV{LC_ADDRESS} = "C";
$ENV{LC_TELEPHONE} = "C";
$ENV{LC_MEASUREMENT} = "C";
$ENV{LC_IDENTIFICATION} = "C";
$ENV{LC_CTYPE} = $lang;
$ENV{LANG} = $languages{$lang}[2];
$ENV{LANGUAGE} = $languages{$lang}[3];
設(shè)置Locale變量之后,調(diào)用Gtk::Rc->parse_string()裝入所需要的字體資源,然后調(diào)用Gtk->set_locale()使Locale設(shè)置生效就可以了。
2. 啟動(dòng)圖形環(huán)境
啟動(dòng)圖形環(huán)境,實(shí)際上就是在系統(tǒng)中運(yùn)行X服務(wù)程序。為了使一個(gè)X服務(wù)器正常運(yùn)行,必須生成正確的XFree86配置文件。在安裝程序的 install_gtk.pm的createXconf函數(shù)中創(chuàng)建XFree86配置文件。關(guān)于XFree86的詳細(xì)配置過程您也可以參看《如何在Linux下實(shí)現(xiàn)設(shè)備的配置》。
#- 這是安裝程序的createXconf函數(shù),它的主要功能是生成XFree86的配置文件。為了使下面
#- 的代碼段更清晰,刪除了一些根據(jù)芯片類型和鼠標(biāo)類型進(jìn)行配置的代碼。因此,下面的代碼和真
#- 實(shí)的安裝程序代碼略有不同而且只支持x86體系結(jié)構(gòu)下的配置文件。
#- 建立真實(shí)鼠標(biāo)設(shè)備的別名鏈接文件/dev/mouse。
symlinkf($mouse_dev, "/dev/mouse");
#- 建立imlib庫(kù)配置文件和調(diào)色板文件的鏈接文件
symlink("/tmp/stage2/etc/imrc", "/etc/imrc");
symlink("/tmp/stage2/etc/im_palette.pal", "etc/im_palette.pal");
#- 生成XFree86配置文件$file
local *F;
open F, ">$file" or die "can't create X configuration file $file";
print F <
#- 下面的文本行,實(shí)際上是XFree86的配置文件。這個(gè)配置文件包含字體路徑設(shè)置、鍵盤設(shè)置、
#- 鼠標(biāo)設(shè)備設(shè)置、監(jiān)視器設(shè)置和屏幕設(shè)置部分。
Section "Files"
FontPath "/usr/X11R6/lib/X11/fonts:unscaled"
EndSection
#- 鍵盤設(shè)置部分,設(shè)置當(dāng)前鍵盤為標(biāo)準(zhǔn)鍵盤。
Section "Keyboard"
Protocol "Standard"
AutoRepeat 0 0
LeftAlt Meta
RightAlt Meta
ScrollLock Compose
RightCtl Control
XkbDisable
END
EndSection
#- 設(shè)置鼠標(biāo)配置,包括設(shè)置鼠標(biāo)的通訊協(xié)議類型以及鼠標(biāo)設(shè)備對(duì)應(yīng)的設(shè)備文件。
Section "Pointer"
Protocol "$mouse_type"
Device "/dev/mouse"
ZAxisMapping 4 5
EndSection
#- 設(shè)置監(jiān)視器配置。由于在定制安裝環(huán)境時(shí),只使用了3.3.6的X服務(wù)器XF86_VGA16和
#- XF86_FBDev,這兩種服務(wù)器的X配置文件都是無法指定顯示分辨率的。對(duì)于XF86_VGA16,
#- 它只能支持640x480的16色顯示方式。對(duì)于XF86_FBDev,它支持的顯示方式是由當(dāng)時(shí)內(nèi)核
#- Framebuffer的工作模式?jīng)Q定的。比如,內(nèi)核以0x311方式啟動(dòng),那么對(duì)應(yīng)的分辨率是
#- 640x480的16位色,那么在使用XF86_FBDev作為X服務(wù)器時(shí),X的對(duì)應(yīng)配置也必須與此完#- 全一致。
Section "Monitor"
Identifier "My Monitor"
VendorName "Unknown"
ModelName "Unknown"
HorizSync 31.5-35.5
VertRefresh 50-70
Modeline "640x480" 25.175 640 664 760 800 480 491 493 525
Modeline "640x480" 28.3 640 664 760 800 480 491 493 525
ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
EndSection
#- 使用XF86_VGA16作為X服務(wù)器時(shí),對(duì)應(yīng)的X配置節(jié)。
Section "Screen"
Driver "vga16"
Device "Generic VGA"
Monitor "My Monitor"
Subsection "Display"
Modes "640x480"
ViewPort 0 0
EndSubsection
EndSection
#- 使用XF86_FBDev作為X服務(wù)器時(shí),對(duì)應(yīng)的X配置節(jié)。設(shè)置Modes為"default",表示選擇
#- 的模式與內(nèi)核啟動(dòng)時(shí)設(shè)置的模式相同。
Section "Screen"
Driver "fbdev"
Device "Generic VGA"
Monitor "My Monitor"
Subsection "Display"
Depth 16
Modes "default"
ViewPort 0 0
EndSubsection
EndSection
END
將上述程序段運(yùn)行之后,X配置腳本就生成了,這時(shí)就可以使用這個(gè)配置腳本文件啟動(dòng)X服務(wù)程序了。下面這段啟動(dòng)X的程序是來自于文件install_steps_gtk.pm。
devices::make("/dev/kbd");
local (*T1, *T2);
open T1, ">/dev/tty5";
open T2, ">/dev/tty6";
#- 執(zhí)行X服務(wù)器程序,返回1表示運(yùn)行成功。
my $launchX = sub {
my $ok = 1;
#- 接管信號(hào)SIGCHLD的處理程序
#- 在進(jìn)程終止時(shí),SIGCHLD信號(hào)被發(fā)送給它的父進(jìn)程。此程序在子進(jìn)程結(jié)束時(shí)調(diào)用。
local $SIG{CHLD} = sub { $ok = 0 if waitpid(-1, c::WNOHANG()) > 0 };
#- 子進(jìn)程執(zhí)行
#- XF86_FBDev -kb -dpms -s 240 -allowMouseOpenFail -xf86config $f
#- allowMouseOpenFail允許鼠標(biāo)打開失敗
unless (fork) {
exec $_[0], "-kb", "-dpms","-s" ,"240",
"-allowMouseOpenFail", "-xf86config", $f or exit 1;
}
#- 測(cè)試X服務(wù)器是否成功激活
foreach (1..60) {
sleep 1;
log::l("Server died"), return 0 if !$ok;
return 1 if c::Xtest($ENV{DISPLAY});
}
log::l("Timeout!!");
0;
};
#- 準(zhǔn)備測(cè)試的X服務(wù)器
my @servers = qw(FBDev VGA16);
foreach (@servers) {
log::l("Trying with server $_");
my $dir = "/usr/X11R6/bin";
my $prog = "XF86_$_";
#- 如果X服務(wù)程序不可執(zhí)行
unless (-x "$dir/$prog") {
#- 刪除/usr/X11R6/bin/下的所有X服務(wù)程序
unlink $_ foreach glob_("$dir/X*");
#- 從安裝盤上拷貝對(duì)應(yīng)的X服務(wù)程序
install_any::getAndSaveFile("HappyLinux/happyinst$dir/$prog", "$dir/$prog") or die "failed to get server $prog: $!";
chmod 0755, "$dir/$prog";
}
#- 根據(jù)/proc/fb文件的內(nèi)容檢測(cè)內(nèi)核是否啟動(dòng)了Framebuffer方式。
if (/FB/) {
!$o->{vga16} && $o->{allowFB} or next;
$o->{allowFB} = &$launchX($prog) and goto OK;
} else {
$o->{vga16} = 1 if /VGA16/;
&$launchX($prog) and goto OK;
}
}
注: (我們?cè)诖藢n}中介紹的是HappyLinux 3.0的安裝程序,它的安裝程序源碼您可以在安裝盤的/HappyLinux/happyinst/usr/bin/perl-install目錄下找到。安裝程序的源碼是由Perl編制的,使用PerlGtk繪制圖形化用戶接口。)


