freebsdのgfortran

FreeBSD 9.1R-p17でgfortranを使っていますが、以下のようなバカみたいなコードをコンパイルしようとすると、

parameter(n1=1000,n2=1000,n3=537)
real a(n1,n2,n3)
a(:,:,:)=0.
end

以下のようなエラーが出てコンパイルできません。
crt1.c:(.text+0x20):再配置がオーバーフローしないように切り詰められました: R_X86_64_PC32 (シンボル `environ' に対して、 COMMON セクション、 /usr/lib/crt1.o 内)
collect2: ld returned 1 exit status

n3=536とすると普通にコンパイルが通ります。なので、メモリの処理の問題だと思われますが、どのように解決すべきなのかよくわかりません。メモリのアドレスの処理のようです。

R_X86_64_PC32というキーワードで検索すると、このページが引っかかりました。intelコンパイラの解説なのですが、このページの2.2.3節の表2.4にそれらしい説明があります。ifortとgfortranはもちろんオプションが違うのですが、とりあえず頭を使わずに、同じオプションを試してみました。

上のコードでn3=537として、test.f90として保存し、

gfortran -mcmodel=medium test.f90

とコンパイルすると、ちゃんとコンパイルが通ってしまいます。もちろん、実行ファイルもちゃんと実行できます。

mediumの部分がsmallでもlargeでもダメです。どうもよくわかりません。

ちなみにcent OS 6.xでは何もしなくても普通にコンパイルが通ります。ますます謎です。

bsfilterの設定

最近、ローカルのspamフィルタが効いていないなぁ、となんとなく思っていたのですが、よく考えたら、メールを読んでいるサーバーを以前と変えたためにspamフィルタを通さないですべてのメールを読んでいる、ということに気がつきました。この変更をしてから1年も経過してようやく気がつくなんて相当マヌケです。

気になるととても気になるので遅ればせながらspamフィルタを通すように設定をすることにしました。以前からspamフィルタにはベイジアンフィルタのbsfilterを使っていたのでこれを使う事にします。

メールを読む環境は、メールサーバーからemacs上のmewでpopでメールを引いてきて読む、というごく当たり前の使い方です。これまでは、fetchmailでpopサーバーから引いてきたメールをprocmailにforwardしてprocmailのレシピでbsfilterに渡して、spam-probabilityをメールに挿入したあと、spam-probabilityが0.9以上のものは自動的にspam用のフォルダに振り分けるようにして、残りは/var/mail/に戻していました。mewは/var/mail/にあるメールをpopで引いて読む、というなんだか文章で書くと面倒なことをしていました。

もちろん同じことをやってもいいのですが、いろいろな事情で非常にやりにくいので、今回は、趣向を変えてbsfilterをPOP proxyとして動作させてbsfilterを介してmewでメールをpopサーバーから引く、という使い方にしました。それなりにちゃんとハマりました。

基本的にはbsfilterが使えるようになっていればOKです。/usr/local/bin/bsfilterとしてインストールされているとします。もちろん、bsfilterに必要なrubyなどもインストールされているという前提です。

1. bsfilterにspamを教える。
まず、bsfilterに正しいメールとspamメールを教えます。

bsfilter --add-spam ~/Mail/from/spam/*
bsfilter --add-clean ~/Mail/inbox/*
bsfilter --update

という具合に学習させます。spamメールがホームディレクトリの下のMail/from/spam/以下に、正しいメールが同じくMail/inbox/以下に保存されているという場合のコマンドです。正しいメールがいろいろなディレクトリに整理されている場合は必要に応じてそれぞれのディレクトリを指定してその下のファイルを全部学習させます。必ずしも全部やる必要はありませんが、たくさん学習させたほうが間違いは少なくなります。

2. bsfilterのPOP proxyを試す
bsfilterをPOPサーバーとmewの間に挟んでちゃんと動くかどうか確認します。

以下のような内容を書いたファイルをbsfilter_proxy.shとして保存します。
/usr/local/bin/bsfilter --pop --auto-update --insert-flag \
--insert-probability --pop-server HOGE.EXAMPLE.COM --pop-port 110 \
--pop-proxy-port 10110 > /dev/null 2>&1 &
ここで、HOGE.EXAMPLE.COMはmewが読みにいっているpopサーバーの名前です。popのポートは標準の110を使っているものとしています。必要な環境が揃っていれば995版ポートを指定してオプションに--sslを追加すればPOP over SSLも使えるようですが(やり方はちゃんと調べてません)、LAN内でのやりとりなので丸裸でpopに接続しています。

sh bsfilter_proxy.sh

とすればbsfilterがproxyとして起動します。ps -ax | grep bsfilterとでもして、bsfilterが起動しているのを確認しておきます。

3. mewの設定
.mew.elには

(setq mew-pop-server "HOGE.EXAMPLE.COM")

が書かれているはずですが、これをコメントアウトして、代わりに

(setq mew-pop-proxy-server "localhost")
(setq mew-pop-proxy-port "10110")

を書きます。proxy-portの10110はbsfilterのオプションの--pop-proxy-portで指定したポート番号です。これで、mewからiを叩いたらpopサーバーに接続してパスワードを聞かれるのでパスワードを正しく入力するとメールを引っ張ってくるはずです。

4. bsfilterの自動起動
2で書いたスクリプトをサーバーを起動したときに手動で動かすというのは絶対に忘れそうで危険です。そのため、起動時に自動的に起動するようにしておきます。

/usr/local/etc/rc.d/bsfilter_proxyというファイルを作って、そこに以下の内容を書きます。

------ここから-------
#!/bin/sh
#
# PROVIDE: bsfilter_proxy
# REQUIRE: DAEMON
# KEYWORD: shutdown


. /etc/rc.subr

name=bsfilter_proxy
rcvar=${name}_enable

command="/usr/local/bin/bsfilter"
command_args="--pop --auto-update --homedir HOME_DIR/.bsfilter/ --pid-file /var/run/bsfilter_proxy.pid --insert-flag --insert-probability --pop-server weber.str.jp --pop-port 110 --pop-proxy-port 10110 > /dev/null 2>&1 &"

load_rc_config $name

#
# DO NOT CHANGE THESE DEFAULT VALUES HERE
# SET THEM IN THE /etc/rc.conf FILE
#
bsfilter_proxy_enable=${bsfilter_proxy_enable-"NO"}
pidfile=${bsfilter_proxy_pidfile-"/var/run/bsfilter_proxy.pid"}

run_rc_command "$1"
------ここまで-------

--homedir HOME_DIR/.bsfilter/というオプションをつけているのは、rc.confを見て起動するとrootで起動するためデータベースを見つけられなくなってしまうからです。なんとなく汎用性にかける書き方ですが、どうせ自分だけが使うということでよいことにしてしまいます。もちろん、HOME_DIRは自分のホームディレクトリへのフルパスにちゃんと置き換えます。

またcommand_argsとpidfileで指定しているpidファイルのパスと名前は整合するようにしておかないとハマります。

さらに、/etc/rc.confに

## POP proxy by bsfilter
bsfilter_proxy_enable="YES"

というのを追記します。

これで、

service bsfilter_proxy start

でbsfilterがpop proxyモードで起動します。しかし、なぜか、/var/run/bsfilter_proxy.pidを出力しないのでserviceコマンドでstatusやstopが効きません。謎です。まぁ、止めるときはps -ax | grep bsfilterとしてPIDを指定してkill -9 PIDとやればよいので気にしないことにします。

これで、mewで取り込んだメールに

X-Spam-Flag: No
X-Spam-Probability: 0.000000

というような行が挿入されます。あとは、mewでこの行を見て振り分けをします。

5. mewで自動振り分け

ここから遅ればせながらbsfilterのソースをダウンロードして展開してできるディレクトリのなかの
mua/mew6.4/mew.el
というファイルを~/.mew.elの後ろにそのまま張り付けます。デフォルトではspam判定されたメールには取り込んだときにDマーク(削除)がつくようになっていますが、これをコメントアウトしてoマーク(振り分け)をつけて+from/spamへ振り分けるように変更しています。

これで、mewを立ち上げてiを叩けば読み込んだファイルにspam判定のヘッダがついて、さらにそれが表示されるようになります。

lhでcleanを、lsでspamを学習させることができます。

花咲舞が黙ってない

池井戸潤の「花咲舞が黙ってない」を読みました。

電車のなかで本を読むと決めたわりには,電車のなかで仕事をしてしまって最近はなかなか本がよめていませんでした。パターンはいつも同じですが,半沢直樹シリーズとの繋がりが垣間見えたりして楽しくよむことができました。たまにはこういう本を読んで元気を出さないとダメだと思いました。