[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[debian-devel:15366] Re: bash の初期化がおかしい
小池@JAISTです。
提示していただいた以下の patch で正しく動作する事を、こちらでも確認し
ました。
>>>>> In [debian-devel : No.15364]
>>>>> ukai@debian.or.jp (Fumitoshi UKAI) wrote:
> --- bash-2.05b.orig/lib/readline/nls.c 2001-10-16 03:32:29.000000000 +0900
> +++ bash-2.05b/lib/readline/nls.c 2002-10-29 14:36:46.000000000 +0900
> @@ -85,9 +85,14 @@
> value, and go into eight-bit mode if it's not C or POSIX. */
> #if defined (HAVE_SETLOCALE)
> char *t;
> + char *lspec;
> + lspec = sh_get_env_value("LC_ALL");
> + if (lspec == 0) lspec = sh_get_env_value("LC_CTYPE");
> + if (lspec == 0) lspec = sh_get_env_value("LANG");
> /* Set the LC_CTYPE locale category from environment variables. */
> - t = setlocale (LC_CTYPE, "");
> + // t = setlocale (LC_CTYPE, "");
> + t = setlocale (LC_CTYPE, lspec);
> if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
> {
> _rl_meta_flag = 1;
ただ、元のコードが以下の様なもので、
1 char *t;
2 t = setlocale (LC_CTYPE, "");
patch 後のコードは以下の様になる訳ですが、
1 char *t;
2 char *lspec;
3 lspec = sh_get_env_value("LC_ALL");
4 if (lspec == 0) lspec = sh_get_env_value("LC_CTYPE");
5 if (lspec == 0) lspec = sh_get_env_value("LANG");
6 t = setlocale (LC_CTYPE, lspec);
いずれの場合も、LC_ALL か LANG の少なくとも1つ(LC_CTYPE は除く)が、設
定されてものと仮定します。
鵜飼さんが作られた patch の場合には、LC_ALL, LC_CTYPE, LANG の順で探索
して、環境変数が定義されていれば、LC_CTYPE の設定にそれを使う、という
事を明示して書かれていると解釈しました。
ですが、setlocale の man page の 50 行目からの段落を読むと、なさった環
境変数の探索は、setlocale(LC_CTYPE, "") の内部でなされる事が保証される
事が、setlocale の仕様として定められていると読めます。
以下、その部分の引用です。適当に桁折りしてあります。
> For glibc, first (regardless of category), the environment variable
> LC_ALL is inspected, next the environment variable with the same
> name as the category (LC_COLLATE, LC_CTYPE, LC_MESSAGES,
> LC_MONETARY, LC_NUMERIC, LC_TIME) and finally the environment
> variable LANG. The first existing environment variable is used.
ですので、元のコード setlocale(LC_CTYPE, "") と同じ動作になると思われ
ますが、いかがでしょうか?
# LC_CTYPE が明示して定義してあれば、元のコードと鵜飼さんのコードの動
# 作は(特に LANG と LC_CTYPE が異なる場合には)違う動作を行うと思います
# が、久保田さんの記事では特にふれておられませんし、私が確認した環境で
# も環境変数 LC_CTYPE は定義しておりません。
それとも、
> 1) ~/.bashrc の LANG=ja_JP.eucJP が処理される
> => setlocale(LC_ALL, "ja_JP.eucJP")
この段階で setenv("LANG", "ja_JP.eucJP") の様な処理がなされないままで、
setlocale(LC_CTYPE, "") が行なわれる為に問題が発生する、という事でしょ
うか?でしたら、そちらの方が本質的な問題だと思われます。まだコードを追っ
てないので、そう行えない、他の要因があるのかもしれませんが。
あと、ここからが本題なのですが、前のメールでも書きましたが、Solaris 7
(Solaris 2.7 は間違いです^^;)では、元のコードで問題無く動作します。微
妙に動作が異なる、特にLC_CTYPE と LC_MESSAGES の設定が異なる場合の動作
は Linux と Solaris で異なっているので、どちらが正しいのか分からないと
(もし、標準のロケールの動作の定義があるのなら)、どちらが問題だとも言え
ないのですが。
例えば、Solaris と Linux で、
1 #include <stdio.h>
2 #include <locale.h>
3 #include <string.h>
4 #include <errno.h>
5
6 int main()
7 {
8 setlocale(LC_ALL, "ja_JP.eucJP");
9 setlocale(LC_CTYPE, "C");
10 puts(strerror(ENOENT));
11 return 0;
12 }
というようなコードを実行させますと、Linux では ??????????????????????
と表示されるのは、今回の問題と同じような動作なのですが、Solaris の場合
には、「ファイルもディレクトリもありません。」と、日本語(EUC-JP)で表示
されてしまいます。今回の件も、この辺りの挙動の差異に似ているので、そう
ではないかと私は考えています。
その点をふまえてざっとコードを読んでみたのですが、locale.c 内で行って
いるロケール関連の処理が、ややおかしいと思えます。まだちゃんと読んでな
いので具体的な話が出来ないのが申し訳ないのですが、前述の LC_CTYPE と
LC_MESSAGES (や、LC_ALL、LANG等)の設定が異なる事があるように思える箇所
がいくつかあります。
# 鵜飼さんの patch は、その不整合な状態を、修正が必要な段階になってか
# ら整合性のある状態にしているように思われます。ですので、結果的に正し
# い動作になったのではないでしょうか。間違いという事も無いと思いますが、
# 正しいとも言えない気がします。だからと言って、問題が発生する事も無い
# と思いますけど。
話が散慢になってしまいましたが、要は何が言いたいかと言うと、「もうちょっ
と問題の根が深いのではないだろうか」という事です。普通は
setlocale(LC_ALL, "") だけすればだいたい良いのに、LC_CTYPE や
LC_MESSAGES などを個別に設定しているようなので、結構問題が複雑になって
いるように思えます。
# shell なので、やみくもに自分自身の環境変数を変更できない事情もあるの
# でしょうが。後付けで足しているのも問題なのかもしれませんが。
何の解決にもなっていないのですが、すいません。自分でも、もう少し調べて
みます。
--
こいけ@じゃいすと(がくせい) <s-koike@xxxxxxxxxxx>