日本語入力に SKK を使ってるんだけど、かといって Emacs は使っていない。そういう変態が新しいホストで SKK な日本語環境を作るときに、この前どうやったんだっけな、といちいち古い記録を調べるのはバカバカしいので、メモをまとめておくぞ、ってなもんで。
ふつーの人がマネをすると、たいてい痛い目を見るので注意。ごく稀にふつーの人にも役に立つことが書いてあったりもするかも。
X は使わないので(Windows からリモートログインして使うので)、X のインプットメソッドはいらない。
インストール先は FreeBSD だが、ports はあまり使わず野良ビルドが多いので、他の OS でも参考になるだろう(だから他人はマネしちゃいかんってば)。
なにはなくとも辞書の用意。こいつは ports をふつーに使う。辞書サーバに cdb 形式辞書を使う dbskkd-cdb を利用するが、cdb な辞書をインストールする japanese/skk-jisyo-cdb ではなく、ふつーの japanese/skk-jisyo をインストールする。理由は後で。
小さな辞書なんかあってもどうせ使わないので、ラージ辞書だけインストールするように以下を /etc/make.conf に記述しておく。
.if ${.CURDIR} == "/usr/ports/japanese/skk-jisyo" SKK_JISYO_TYPE= L .endif
make install すれば /usr/local/share/skk/SKK-JISYO.L がインストールされる。
skkfep内蔵jvimをインストールする。基本的にドキュメントにあるとおり。
% tar xvzf jvim3.0-j2.1b-skk1.2.18+skkfep0.86c-kh1.2.10+ari1.00a-kh1.2.2.tar.gz
インデックスつき辞書作成用のツールをコンパイルする。ari 本体はいらない。
% cd jvim-skkfep-ari/ari % make skksrch # cp skksrch /usr/local/bin
skkfep ではなく、libskkfep.a を作る。
% cd ../skkfep % ln -s ../ari/skksrch.c % vi config.h
config.h の最低限必要な修正は、#include "configs/solaris2.h" となっている行を OS に合わせて変更すること(今回は FreeBSD なので configs/freebsd.h に変更)、SKKFEP_LIB を #define すること(必須!)。
あとは、後のメンテのことを考えて
-# define SKKSRCH_DIC "/usr/local/share/skk/SKK-JISYO.L" +# define SKKSRCH_DIC "/usr/local/share/skk/SKK-JISYO.L.idx"
に変更。それ以外はお好みで。わしの場合は #define KUTOUTEN しておく。
コンパイルする。
% make libskkfep.a
skk を使える jvim の本体をコンパイルする。
% cd ../jvim/src % cp makjunix.mak Makefile % vi Makefile % diff -u makjunix.mak Makefile --- makjunix.mak Sat Jan 18 14:45:36 2003 +++ Makefile Mon Dec 18 11:43:07 2006 @@ -78,7 +78,7 @@ BINLOC = $(PREFIX)/bin ### Name of target -TARGET = vim +TARGET = jvim ### Location of man page MANLOC = $(PREFIX)/man/man1 @@ -100,7 +100,7 @@ MANFILE = ../doc/vim.1 -HELPFILE = ../doc/vim.hlp +HELPFILE = ../doc.j/vim.hlp # # PART 2: various choices @@ -214,6 +214,10 @@ #MACHINE = -DBSD_UNIX -DUSE_LOCALE -DUSE_X11 #CC=gcc -O -Wall -traditional -Dconst= -I$(X11INCDIR) #LIBS = -ltermlib -L$(X11LIBDIR) -lX11 + +MACHINE = -DBSD_UNIX +CC=cc -O3 -pipe -Wall +LIBS = -ltermlib # like generic, but with termcap, for Linux, NeXT and others (NOT TESTED YET) # standard cc with optimizer
コンパイルオプションは OS によっててきとーにいじる。あとは make してインストール。
% make # make install
~/.jvimrc に最低限以下を設定すると、入力モードで CTRL-J を打つと skk な入力が可能になる。現時点では辞書がないので、かな入力だけで漢字変換はできない。
:set fepkey=J :set fepctrl
skksrch をインストールしたので、jvim+skkfep で使うインデックスつき SKK 辞書を用意する。また、skkfep は Lisp を理解しないので、変換候補がふつーの文字列ではなく Lisp コードになっているものはあると邪魔。また、変換候補にコメントが入ってる形式の辞書も扱えないのでこれも邪魔。インデックスつき辞書に変換する前に、これらの邪魔なものを取り除いてやる。なお、コメントについては ports で make WITH_SKKJISYO_DELCOMMENTS=yes してやれば除去されるが、lisp の方は消えないのでどっちにしろ変換が必要。
/usr/local/share/skk/Makefile を用意。中身は以下。
all: SKK-JISYO.L.idx SKK-JISYO.L.cdb SKK-JISYO.L.idx: SKK-JISYO.L awk 'BEGIN { FS = "/" } \ { \ if(/^[^;]/){ \ f = 0; \ s = $$1; \ for(i = 2; i < NF; i++) { \ if($$i !~ /^\([a-z]/) { \ sub(/;.*/, "", $$i); \ s = s "/" $$i; \ f = 1; \ } \ } \ if(f) print s "/"; \ } else { \ print \ } \ }' SKK-JISYO.L > tmpdic /usr/local/bin/skksrch -index tmpdic > SKK-JISYO.L.idx rm -f tmpdic SKK-JISYO.L.cdb: SKK-JISYO.L.idx awk '/^[^;]/ { \ s = substr($$0, index($$0, " ") + 1); \ print "+" length($$1) "," length(s) ":" $$1 "->" s \ } \ END { print "" }' SKK-JISYO.L.idx |\ /usr/local/bin/cdb -c SKK-JISYO.L.cdb
make すると、SKK-JISYO.L.idx が作成される。SKK-JISYO.L.idx も作ろうとするが、現時点では失敗する。.idx を元の L 辞書と diff ってみてどう違うか確認してみるとよろし。
jvim で漢字変換できることを確認しておく。
辞書サーバのインストール。cdb に変換した辞書を利用する dbskkd-cdb を使う。jvim+skkfep は辞書ファイルを直接アクセスできるようにコンパイルしたので、別に必須じゃないけど、Windows な Meadow からも使うこともあるので、入れておくと便利(UNIX では Emacs は使わないくせに、Windows では使う変態ですが何か?)
本家 djb の cdb を使ってもいいんだけど、とくに理由はないがなんか互換ライブラリの気分なので、tinycdb を使う。FreeBSD なら ports からインストールできる。
% cd /usr/ports/database/tinycdb % make # make install
tinycdb をインストールしたことで cdb コマンドが使えるようになった。cdb 形式辞書を作るため、/usr/local/share/skk で再度 make する。オリジナルの SKK-JISYO.L と、それから加工された .idx と .cdb ができているはず。
dbskkd-cdb は FreeBSD の ports にちゃんと存在しているが、djb 版 cdb ではなく互換ライブラリの tinycdb を使うことにしたので、ports は使えない(使ってもいいけど)。まあ、ports を使うよりカンタンかもしれん。
% tar xvzf dbskkd-cdb-1.71dev.tar.gz % cd dbskkd-cdb-1.71dev % gcc -DSERVER_DIR=\"/usr/local/share/skk\" -O2 -pipe -I/usr/local/include -L/usr/local/lib dbskkd-cdb.c -lcdb -o dbskkd-cdb # cp dbskkd-cdb /usr/local/libexec
tinycdb のライブラリとヘッダがちゃんとインストールしてあれば、Makefile なしでコンパイルできる。
動作確認。root で以下を実行して、「a」に対する変換候補が得られることを確認。
# echo '1a ' | /usr/local/libexec/dbskkd-cdb 1/α/エー/エイ/アー/а/ア/ dbskkd-cdb: pid 99679 end of file detected
この節はとくに変態的なことはしない。というか、dbskkd-cdb の方が変態的なのを、こちらで正気に戻す作業をする。dbskkd-cdb を使うユーザすべてに有用なはず。とくに、FreeBSD の ports でインストールしたときに出力される
Note for inetd users: Add following line to /etc/inetd.conf skkserv stream tcp nowait root /usr/local/libexec/dbskkd-cdb dbskkd-cdb If dbskkd-cdb 1.01 was running, please update your /etc/inetd.conf line.
というメッセージに騙されて、このとおり設定してしまった場合は、この節の方法で設定しなおすべし。これは明らかに間違っているので、けっして従ってはいけない(だいぶ前に ports のメンテナにメールで指摘したんだけど無視されたよ)。
dbskkd-cdb は djb なツールなので、tcpserver から起動することを想定していて、inetd から使うことなんてまったく考えていない。どちらも、いわゆるスーパーデーモンなのだが、動作上のもっとも大きな違いは、子プロセスの標準エラー出力の扱いである。
dbskkd-cdb は tcpserver での利用を前提としているので、ログを自分で syslog に投げず、標準エラー出力に垂れ流すだけである。tcpserver で使うのならばそれで問題ないが、inetd で使うときはログメッセージなのにクライアントにそのまま返されてしまう。上述の FreeBSD ports のメッセージのように、inetd.conf にそのまま dbskkd-cdb を起動する設定を書いてしまうとこの問題があってよろしくない(これでも動くが、たまたまである)。
また、dbskkd-cdb は chroot() するので、root 権限で起動する必要がある。本来は chroot() した後で低い権限に setuid()/setgid() するのだが、上述の設定はこれに必要な設定も抜けている。djb なツールは UID/GID という環境変数にユーザ ID /グループ ID を入れておくとその権限に setuid()/setgid() するというお約束がある。dbskkd-cdb も例外ではない。これが抜けていた場合、権限を放棄せず、ずっと root のまま動き続ける。
FreeBSD ports のメッセージそのままに設定してしまうと、以上の2点が問題になる。これを解消するために、ラッパースクリプトを用意してやって、そのラッパーの方を inetd.conf に設定してやる必要がある。
#!/bin/sh SKKSERV=/usr/local/libexec/dbskkd-cdb UID=`id -u nobody` GID=`id -g nobody` exec env - UID=$UID GID=$GID $SKKSERV 3>&2 2>&1 1>&3 | /usr/bin/logger -t dbskkd-cdb -p daemon.info #exec env - UID=$UID GID=$GID $SKKSERV 2>/dev/null
これで chroot() 後の権限を nobody に変更し、かつログはクライアントに返さずに syslog に送るようになる。どうせたいしたログは取れないので、捨てちゃっていいや、という場合は exec の行をコメントアウトしてるものに入れ替える。
このラッパースクリプトを /usr/local/libexec/skkserv とすると、inetd.conf の設定はこんな感じ。
skkserv stream tcp nowait root /usr/local/libexec/skkserv skkserv
参考までに、3>&2 2>&1 1>&3 というのはシェルの標準出力と標準エラー出力を入れ替えるリダイレクト。前述のように、tcpserver は標準出力だけをクライアントに返して、標準エラー出力はログ用に使うが、inetd はどちらもクライアントに送り、そして dbskkd-cdb は tcpserver しか考慮してないので、ログを標準エラー出力に吐いてしまう。ということで、標準エラー出力(ログ)を標準出力に切り替えて /usr/bin/logger に食わせ、標準出力(変換候補)は標準エラー出力に切り替えてクライアントに返す。これが上の奇怪なリダイレクトの意味である。
inetd を kill -HUP したら、動作確認。
% telnet localhost skkserv 1a ← a の後にスペース1個 1/α/エー/エイ/アー/а/ア/ ← 「a」に対する変換候補が返ってくる [CTRL-D]
以上で終了。おつかれさまでした。