[PREVIOUS CHAPTER] [NEXT CHAPTER]

2 libexec/fml_local.pl

    2.1	ローカル配送のためのインターフェイス (libexec/fml_local.pl)

    ようはループを止めようと思ったものの、作り終わってみたら な〜んか
    slocal と同じになっちゃいましたね(馬鹿)。まぁ tk-slocal とか世の中には
    あるんで、perl-slocal があってもいいでしょ(開きなおり(苦笑))

    slocalと違うのは、制御するファイルのFieldの数とか、正規表現が使えると
    か、(必要なら fml のlibrary を呼び込んで)perlの関数を直接呼べるとか…
    という upper compatibility です。

    歴史的に(デフォールトでは)「最後にマッチするエントリを実行する」という
    ところが決定的に違います。諸葉の都合で、例えば簡単に学習するvacationプ
    ログラムへと拡張できるための仕様だったのですが、今となっては設計のミス
    のような気がします。設定で

    	FIRST_MATCH

    とすれば 最初にマッチしたパターンを実行するようになります。slocal なん
    かと同じです。

    	libexec/fml_local2.pl

    のほうはデフォールトが「最初にマッチしたパターンを実行」するようになっ
    ています。
    ＃実は単なるリンクで、自分の名前を見て実行を変えているだけです

    2.2	Overview

    ~/.forward は通常アドレスのフォワードに使われますが、本質的に
    /etc/aliases と同じように作動しますので、ここにプログラムを設定すれば
    自動仕分けやこじんまりとした(手抜き)MLを実行することが可能です。

    実際の仕分けやプログラムへ渡す前の前処理段階つまりヘッダ等のパターンを
    見て何をすればいいのか判定するプログラムが libexec/fml_local.pl です。

    	libexec/fml_local.pl
    	libexec/fml_local2.pl

    と２つありますが、パターンマッチの仕方が違うだけです。後述のように
    fml_local.pl は最後にマッチした条件(以下 LAST MATCH)を実行、
    fml_local2.pl は最初にマッチした条件(以下 FIRST MATCH)を実行します。

    2.3	fml_local と ~/.forward の設定

    ~/.forwardに

       "|/usr/libexec/fml/libexec/fml_local.pl -user username || exit 75"

    とか書いて使います。username はあなたの account名です。

    SYNOPSIS:
      fml_local.pl [-Ddh] [-f config_file] [-user username]
        -h     this help
        -d     debug mode on
        -D     dump variable
        -f     configuration file for ~/.fmllocalrc
        -user  username

    デフォールトでは $HOME/.fmllocalrc という設定ファイルにしたがってパター
    ンマッチングとその処理を実行します。

    この時 ~/.fmllocalrc を上から順番にパターンマッチするか？否か？を試し
    て“最後にマッチするエントリを実行します”。

    これは主に歴史的な理由で last match なのですが、FIRST_MATCH を定義する
    か libexec/fml_local2.pl を使えば最初にパターンマッチした処理を実行す
    るように変更できます。

    以下 LAST MATCH する場合について記述しています。FIRST MATCH の場合は逆
    になるので注意して下さい。

    2.4	~/.fmllocalrc

    fml_local.pl は ~/.fmllocalrc で制御します。見本が etc/dot_fmllocalrc
    です。

    いつものように
    	# ではじまる行はコメント
    	空行は無視して次へ進む

    です。

    デフォールトは自分のスプールへ、そしてローカルなＭＬの配送はスプールへ
    落すようにセットしてループしないようにするべきです。

    だから、LAST MATCH の場合、最後に必ず

    	From		自分	&	MailLocal
    	X-MLserver 	\S+	& 	MailLocal

    のエントリをかくことがループを防ぐためにもっとも大事になります。

    もちろんループを検出した場合は強制的に MailLocal を実行して /var/mail
    等へ入れてしまいます。

    さらに、ＭＬをやるときは

    	From		自分	&	MailLocal

    	# ＭＬの設定
    	X-MLserver 	\S+	& 	MailLocal

    のように挟んでください。そうしないと自分ではＭＬへ投稿できません（苦笑）
    ＃後にあると From がマッチしてしまう(last match の場合の例であることに注意)

    2.5	~/.fmllocalrc の各フィールド

    ４つの変数をSPACE or TABで区切ってやってほしいことをかきます。

    	フィールド パターン 実行のタイプ 実行すること

    です。空行で区切られた各パラグラフが条件文です。

    	フィールド1 パターン1
    	フィールド2 パターン2 実行のタイプ 実行すること

    のように複数行あるパラグラフはANDの条件文です。つまり、上の場合
    「フィールド1 パターン1」かつ「フィールド2 パターン2」の条件を満たすな
    ら実行する…という意味になります。

    それ以外に変数を定義できます。

    例：
    	HOME	/home/beth/fukachan
    	DIR	/home/beth/fukachan
    	DEBUG

    それらの変数は実行内容の中で展開して使われます。セットされる変数一覧
    （@VAR の中身）は後述します(2.10)

    また”フィールド パターン”はメールのヘッダのすべての行について、

    	if (そのフィールドの値 =~ /パターン/ )

    の形で判定されます。つまり

    	subject: の特定のキーワードでＭＬを起動する

    や、X-ML: というのをヘッダにつけてもらい

    	X-ML:	uja というフィールドがあったらＭＬを起動する

    等の設定も自由自在ます。しかし逆に意識的に設定しない限り

    	Subject: uja
    	Subject: ujauja
    	Subject: Elena Sayori uja uja UJA

    等はすべて同じものに見なしてしまいます。

    各フィールドの意味は次の通りです。

    フィールド	To, subject, 等。なんでもいい。
    		body という特別なフィールドもあります
    		これはメール本文を仮想的にヘッダのフィールドと同様に扱
    		うことで実装しています。

    パターン	perlの正規表現が使えます。
    		スペースとかは含めないので
    		get\s+(\S+)
    		こんな形になります。
    		() でマッチした変数は順に
    		$F1 $F2 $F3 に設定されます。
    		話をややこしくしないために $F1 等はグローバル変数です。

    実行のタイプ	& は perl の関数呼びだし
    		> は そのファイルにアペンドです
    		| は パイプで渡します。
    		UNIX FROMつきのまま渡します
    		UNIX FROMを抜いた形でプログラムへ渡すには
    		|の代わりにmhと書いてください
    		（mhへ渡すことを想定している）

    実行するもの	実行するもの。関数 or ファイル

    パターンマッチルーチンの後 $TYPE と $EXEC というグローバル変数に実行す
    るべきタイプと実行するべきプログラムが設定されます。

    2.6	パターンの記述に用いることのできる正規表現

    以下で実際に出てくる基本的な正規表現をすこし説明します。

    	. 	なんでもいいから一文字
    	\s 	空白文字 e.g. space TAB
    	\S 	空白でない文字
    	+ 	１個以上
    	* 	０個以上です。
    	\S+	１個以上の空白でない文字列
    	.*	０個以上の文字列(なんでもいい)

    	()でくくったものがマッチしたもので fml_local.pl では
    	左から順番に グローバル変数 $F1 $F2 $F3 にセットされます

    2.7	パターンの例

    例１：
    	to	(uja)		|	$DIR/fml.pl $DIR $DIR

    To: フィールドのどっかに uja という文字列があれば、それにマッチする
    例えば To: fukachan@sapporo.iij.ad.jp (uja)

    なお、
    	to	\(uja\)		|	$DIR/fml.pl $DIR $DIR

    は uja ではなく (uja)  にマッチします。

    例２：

    	Subject	get\s+(\S+)	&	sendback

    例えば Subject: get GUIDE FILE の GUIDE だけにまっち

    例３：
    	body	get my spool (.*)	& 	getmyspool

    メール本文に
    	get my spool uja uja
    とあれば、"uja uja" の部分を $F1 にセットします。.* だからスペースにも
    マッチしてます。これでパスワードに空白も使えますね。

    2.8	~/.fmllocalrc でＭＬを行なう例

    LAST MATCH に注意！

    ＭＬをセットする ~/.fmllocalrc の例：

       DIR	/usr/local/fml

       From		fukachan	&	MailLocal

       to		\(uja\)		|	$DIR/fml.pl $DIR $DIR

       to		\(sayori\)	|	$DIR/fml.pl $HOME/var/sayori

       X-MLserver	\S		&	MailLocal

    	To: username@somewhere.jp (uja)
    というメールがきたら
    	"|$DIR/fml.pl $DIR $DIR"

    という普通の形でＭＬを作動させるというものです。
    ここで $DIR は上の DIR の行の値で展開されます。

    このfml.pl は普通のfml.pl です。パッチとかをあてる必要はありません。
    つまり、fml_local.pl がヘッダをみて何を起動すればいいかを
    判断するので、起動するべきものは普通のＭＬサーバでいいわけです。

    また、 (uja)  は
    	うじゃＭＬ（/usr/local/fmlの下にconfig.phでカスタマイズ）を、

    (sayori) はまた別の
    	さよりちゃんＭＬ（/usr/local/fml/var/sayori/config.ph）

    を起動します。

    これ以外の、From: fukachan…（@phys とかついてても なくてもいい） や、
    X-MLserver: フィールドのあるメール、いづれにもマッチしないメールはすべ
    て /var/mail/fukachan のように sendmail が普通スプールする場所にスプー
    ルされます。

    2.9	フィールドはヘッダ以外に body  があります

    これはパスワードを必要とするようなものは、本体でパスワードを書くべきで
    す。エラーメールではヘッダはまるみえですから

    body	getmyspool\s+(\S+)	&	getmyspool_pw

    とか設定すれば、Providerから会社の自分のスプールの内容を夜中に読むとかが
    できるようになります。
    例：
    % echo "getmyspool password-is-required" |Mail 自分のアドレス

    2.10	変数一覧

    もし変数を明示的にセットしないときは適当な値がデフォールト設定されます。

        @VAR = (HOME, DIR, LIBDIR, FML_PL, USER, MAIL_SPOOL, LOG, TMP,
    	    TMP_DIR, PASSWORD, DEBUG, AND, ARCHIVE_DIR, VACATION,
    	    MAINTAINER, MAINTAINER_SIGNATURE, FS,
    	    LOG_MESSAGE_ID, SECURE_FML_LOCAL,
    	    FIRST_MATCH, SLOCAL,
    	    MY_FUNCTIONS, CASE_INSENSITIVE, MAIL_LENGTH_LIMIT);

    これらの USER DEFINED 変数は fml_local 中ではそれぞれ

    	@VAR $HOME $DIR $LIBDIR $FML_PL $USER $MAIL_SPOOL $LOG $TMP
    	$TMP_DIR $PASSWORD $DEBUG $AND $ARCHIVE_DIR $VACATION
    	$MAINTAINER $MAINTAINER_SIGNATURE $FS $LOG_MESSAGE_ID
    	$SECURE_FML_LOCAL $FIRST_MATCH $SLOCAL $MY_FUNCTIONS
    	$CASE_INSENSITIVE $MAIL_LENGTH_LIMIT

    のような USER DEFINED 変数中に格納され Refer することができます。

    # USER	-user fukachan で設定する変数と同じ意味
    USER	fukachan

    # HOME	$HOME変数。
    # Bourne Shell 風にしているので、~/ を展開するようにはなっていません
    HOME	/home/axion/fukachan

    # fml.pl のある場所。でも使ってない変数…:-)
    FML_PL	/home/vivian/fukachan/work/EXP/fml.pl

    # $DIR 変数の設定。下で使われると $DIR を次の値で展開するため
    DIR	/home/vivian/fukachan/work/EXP

    # $LIBDIR 変数の設定。下で使われると $LIBDIR を次の値で展開するため
    LIBDIR	/home/vivian/fukachan/work/EXP

    # メールスプールの場所
    MAIL_SPOOL	/var/mail/fukachan

    # デバッグモード
    DEBUG

    # From: であり、エラーメールが返る場所。もっともふつう〜は
    # 自分自身以外に設定仕様がないですね
    MAINTAINER 	fukachan@phys.titech.ac.jp

    # From: in MAINTAINER's SIGNATURE
    # From: $MAINTAINER ($MAINTAINER_SIGNATURE) になる
    # e.g. 返るメールのFrom:が、
    # From: fukachan@phys.titech.ac.jp (Prisoner No.6 Fukachan)
    # になる
    MAINTAINER_SIGNATURE	Prisoner No.6 Fukachan

    # ログファイル デフォールトは ~/log
    LOG		$HOME/work/fml/log

    # パスワード
    PASSWORD	uja uja

    # get とかで使う アーカイブの置き場所。もし設定してないと HOME
    ARCHIVE_DIR	/home/uja/uja/work/archive

    # Vacation program compatible で vacation の働きもする。
    VACATION	/home/uja/uja/.vacationrc

    # フィールドセパレータを変更する
    FS	\s+

    FS	:
    とすれば、.fmllocalrcの設定は From:fukachan:&:MailLocal とかくことになる

    # ユーザーが自分用に設定した関数を 別のファイルにしまいたいなら
    # そのファイル名を設定する。デフォールトは ~/.myfunctions.pl
    MY_FUNCTIONS	/home/your-function-file

    INC	include-path

    必要なら、fml のいろいろな ライブラリファイルを include してより高度な
    関数を使うことが可能です。そのライブラリが置いてある場所を指定します。
    いくつ指定してもＯＫです。
    値は指定した順番に @INC に代入されます。そして、その順番にサーチされま
    す。

    MAIL_LENGTH_LIMIT	2900

    getmyspool2 では分割して送り返す関数を呼びます。この分割のしかたで、
    何行でファイルを分けるか？ をきめます。
    たとえば、ヘッダが２、３０行あると仮定すると、余裕を見て２９００とかし
    ておけば、３０００行制限のあるＢＢＳでも受け取れるようになるでしょう。

    TMPDIR			./tmp

    $HOME からの相対パスをかく。デフォールトは ./tmp（つまり $HOME/tmp ）
    ＃なければ、つくります。

    SECURE_FML_LOCAL	0

    最終的に実行されるコマンドのsecurity予備チェック。自分で書いたコードで
    も Special character があれば、Insecure となってしまうので、.fmllocalrc
    には特殊も時は使わず、定数を埋め込んだ形で書くのが望ましい。
    その上で Secure にするべきであろう。

    2.11	フィールド設定の例
    ＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
    #field		pattern		type	exec

    # (/usr/libexec/mail.local にならう)
    # スプール （例 /var/mail/fukachan ）に Appendします
    # From:fukachan の場合、From:fukachan@phys.titech...もマッチする
    From		fukachan	&	MailLocal

    # MH の folder へいれる。MH本来の slocal はこう使うんだろうなぁ
    From		fukachan@phys	mh	/usr/local/lib/mh/rcvstore +inbox

    # 外国ＴＶシリーズＭＬからのメールは
    # TO:enterprise@phys.titech.ac.jp になるから、それにマッチしたら
    # ~/Mail/enterprise というフォルダーにいれる
    To		Enterprise@phys mh	/usr/local/lib/mh/rcvstore +enterprise

    # File Retrieving
    # perl の関数を呼ぶ。(\S+)でマッチしたものが ↓$F1 に置き換えられる。
    Subject		get\s+(\S+)	|	/usr/bin/Mail -s $F1 $From_address

    # Exec ML
    # ＭＬサーバ fml.pl を呼ぶ。
    # 今の場合管理者宛のメールは上のFrom や X-MLserverでスプールに落すので
    # ループはしない

    to		(uja)		|	$DIR/fml.pl $DIR $DIR

    # これは最後にマッチするべき、これで絶対にループしないはず
    # MailLocal は
    # (/usr/libexec/mail.local にならう)
    # スプール （例 /var/mail/fukachan ）に Appendします
    # From:fukachan の場合、From:fukachan@phys.titech...もマッチする
    # From		fukachan	&	MailLocal
    # もし ML からきたら、ローカルにおとす
    X-MLserver	\S		&	MailLocal

    ＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿

    2.12	ファイルを送り返す設定の例

    ~/.fmllocalrc
    ＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
    # Subject: get ファイル名
    # アーカイブの“ファイル名”のファイルを
    # Reply-to: へ もしなければ From: へ送り返す

    Subject         get\s+(\S+)     	&	sendback

    # Subject: GUIDE
    # アーカイブの ファイル GUIDE を
    # Reply-to: へ もしなければ From: へ送り返す

    Subject         (GUIDE)  	   	&	sendback

    # メール本文に "getmyspool パスワード" とかいて
    # 家から (大学|会社)のメールスプールを 家に送ってもらう
    # 一応スプールのメールは消さない
    # Reply-to: へ もしなければ From: へ送り返す

    body            getmyspool\s+(\S+)	&	getmyspool_pw

    ＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿

    2.13	fml_local BUILD-IN Functions 一覧

[PREVIOUS CHAPTER] [NEXT CHAPTER]