[FreeBSD-users-jp 96344] Re: FreeBSD-11.2 の ja_JP.eucJP 環境

WATANABE Kazuhiro CQG00620 @ nifty.ne.jp
2018年 11月 6日 (火) 13:23:28 UTC


渡辺一寛です。

On Wed, 24 Oct 2018 11:51:01 +0900,
Kouichi Hirabayashi wrote:
> 不具合自体は、ja_JP.eucJP 環境で /bin/sh に非 ASCII 文字を
> 入力すると正常終了してしまうというもので、起動した sh に
> <Alt-a> などをキー入力したり、EUC 漢字コードを入力あるいは
> paste することで確認できます。

手元で 11.2-RELEASE/amd64 をセットアップしてみましたが、確かにそうなり
ます。ja_JP.SJIS でも同様です。

# UTF-8 については後述。

> /bin/sh が ja_JP.eucJP 環境で使えなくなってしまった理由は、
> 
>   /usr/src/lib/libedit
>   /usr/src/bin/sh
> 
> の両方が ja_JP.eucJP 環境が使えなくなるように変更されてしまっ
> たことにあります。
> 
> sh については parser.h で定義される字句構文解析用の文字種識別
> token に EUC-JP 漢字コードの 2 byte 目の使用範囲と重複する
> 値を使ってしまったため、EUC-JP 文字や Atl-A, Alt-B, .. な
> どを含む文字列が解釈不能になります。
> 
> libedit でも EUC-JP が使えないように書き換えられていますが、
> read.c には「#ifdef  KANJI」といったコードが残っていて、そ
> の「KANJI」を define すると compile できなくなるといった状
> 態で、書き換えの真の意図は理解できません。EUC-JP が使えない問
> 題に関係するのは chartype.c, el.c, read.c といったところ
> です。
> 
> EUC-JP 環境が必要な状況での対策としては、libedit と sh の
> 両方を書き換えて EUC-JP が使える sh を作る方法以外に、sh の
> 使用をあきらめて、csh, tcsh bash, rbash で代替する方法が
> あります。

FreeBSD ワークショップでも話が出た (出ない?) ようですが、私が手元でやっ
てみた具体的な回避策を 2 つ。

(1) sh を作りなおす

sh のソースを眺めてみましたが、NO_HISTORY というのを定義すると libedit
(editline(3)) の機能を使うコードがオミットされるようです。試しに

Index: bin/sh/Makefile
===================================================================
--- bin/sh/Makefile     (revision 339812)
+++ bin/sh/Makefile     (working copy)
@@ -19,7 +19,7 @@
 # utilities of the same name are handled with the associated manpage,
 # builtin.1 in share/man/man1/.
 
-LIBADD=        edit
+#LIBADD=       edit
 
 CFLAGS+=-DSHELL -I. -I${.CURDIR}
 # for debug:
Index: bin/sh/shell.h
===================================================================
--- bin/sh/shell.h      (revision 339812)
+++ bin/sh/shell.h      (working copy)
@@ -51,6 +51,7 @@
 
 #define        JOBS 1
 /* #define DEBUG 1 */
+#define NO_HISTORY
 
 /*
  * Type of used arithmetics. SUSv3 requires us to have at least signed long.

として sh を作りなおしたところ、ja_JP.eucJP または ja_JP.SJIS な環境で
も、コマンドラインに日本語入力できるようになりました。libedit の編集機
能に加えてヒストリも使用出来なくなりますが、少し使ってみた限り、基本動
作に支障はないように見えます。

(2) set +o emacs してコマンドライン編集機能を無効にする

sh を起動後に set +o emacs (または set +E) するか、sh を "sh +E" で起
動すると、(1) と同様にコマンドラインに日本語入力できるようになりました。

なお editrc(5) によって libedit の編集機能を無効にすることもできます。
設定すると確かに無効になるのですが、日本語入力に関しては効果がありませ
んでした。

> /bin/sh を EUC-JP で使えなくした原因の一つである libedit
> のソースの comment
> 
>  /* FIONREAD attempts to buffer up multiple bytes, and to make that work
>   * properly with partial wide/UTF-8 characters would need some careful work. */
> 
>   /*
>    * We don't support other multibyte charsets.
>    * The second condition shouldn't happen
>    * and is here merely for additional safety.
>    */
> 
> を見ると、ASCII と UTF-8 限定という意図かもしれませんが、も
> しそうなら、/bin/sh でも sh を起動した時点で、ja_JP.eucJP
> 環境の場合は「ja_JP.eucJP は使えない」という警告を出して終
> 了すべきですし、/bin/sh はシステムの根底の一つですから、
> ja_JP.eucJP 自体をなくすといった作業と告知も必要なはずで、
> 理解に苦しみます。

現在の libedit は NetBSD 由来なので、試しに NetBSD 8.0 をセットアップ
してみたところ、FreeBSD 11.2 と同様の結果になりました。

ja_JP.eucJP または ja_JP.SJIS な環境での、コマンドラインへの日本語入力
の可否は次のようになります。

       		FreeBSD 11.2		NetBSD 8.0
素の sh		入力不可・突発終了	入力可
set -o emacs	入力不可・突発終了	入力不可・突発終了
set +o emacs	入力可			入力可

FreeBSD 11.2 と NetBSD 8.0 の、素の sh の挙動の違いは、インタラクティ
ブシェルとして sh を起動した時に、編集機能がデフォルトで有効かどうかに
因るもののようです。編集機能を明示的にオン/オフすれば、ほぼ同じ挙動に
なりました。

# FreeBSD はデフォルトで有効。
# NetBSD はログインシェルが sh の場合に有効。

なお NetBSD 7.2 の挙動は少し違って、編集機能が有効な場合、日本語入力は
無視され、表示もされません。このほうが突発終了するよりはマシかも知れま
せん。

***

まっとうな解決策は、EUC/SJIS 環境でも今まで同様にマルチバイト文字の入
力が可能なように修正することだと思いますが、NetBSD のように、sh のコマ
ンドライン編集機能をデフォルトで off にするだけでもいいかなと思います。

sh のコマンドライン編集機能、ワンライナーをちょろちょろ書くには十分で、
便利に使ってたんですけどね。

***

ついでに ja_JP.UTF-8 な環境でも、sh のコマンドラインへの日本語入力を試
してみました。

FreeBSD 11.2 の場合、編集機能の有効/無効に関係なく入力できます。ただし
カーソルキーで履歴を辿ったり、編集を行なったりすると、表示がずれたり抜
けたりします。これは表示だけの問題のようで、Ctrl-L で再表示すると直り
ます。

NetBSD 8.0 の場合も、編集機能の有効/無効に関係なく、問題なく入力できま
す。また履歴も編集も問題ありません。libedit のリビジョンが NetBSD 8.0
のほうが新しいので、それによる違いかも知れません。
---
WATANABE Kazuhiro (CQG00620 @ nifty.ne.jp)


freebsd-users-jp メーリングリストの案内