<!-- -*- mode:text coding:euc-jp -*-
   $FML: config.cf.sgml,v 1.16 2008/08/18 13:21:42 fukachan Exp $
-->


<chapter id="internal.config.cf">
	<title>
	設定ファイル config.cf
	</title>


<!-- ======================================= -->
<sect1 id="config.cf">
	<title>
	ＭＬごとの設定ファイル config.cf
	</title>

<para>
各ＭＬごとにさまざまなカスタマイズをすることができます。
この点は &fml4; でも &fml8; でも同様です。
</para>

<para>
そのために &fml4; では、
各ＭＬのホームディレクトリ $DIR (例: /var/spool/ml/elena)に
config.ph というファイルがあります。
これは .ph という名前でわかるとおり、普通の perl スクリプトです。
</para>

<para>
一方 &fml8; では config.cf というファイルになっています。
.cf のフォーマットは Postfix や .ini 風の
<screen>
変数 = 値
</screen>
形式になっています。
複数行の値も可能です(後述)。
</para>

<para>
perl モジュールと同様に、
=cut の後は
perl スクリプトが書けるようになっています。
よって、
「キーワード = 値」
形式の記述は =cut の前に書く必要があります。
</para>

<sect2>
	<title>
	&fml4; の諸問題
	</title>

<para>
&fml4; の perl スクリプト方式には、いくつか問題があります。
</para>

<para>
メリットとしては、
perl スクリプトなので、perl が許す限りの自由な書き方ができます。
これは人間にとっては嬉しいのですが、
機械処理の観点からは問題です。
というのは、 
makefml や CGI をはじめとする設定インターフェイスを書きにくいのです。
そこで &fml4; では、
cf というファイルと
config.ph という2つのフォーマットの異なるファイルが使われることになりました。
<footnote>
<para>
.mc から .cf を作る点で、なんとなく sendmail みたいですね;)
</para>
</footnote>
しかしながら、
これでは２つのファイルに分かれてしまうため保守が大変です。
</para>

<para>
よって &fml8; では、
設定インターフェイスの構築にやさしい新フォーマットとしました。
それが config.cf で、
本質的に Postfix 風フォーマットですが、少し拡張されています。
</para>

</sect2>
</sect1>


<!-- ======================================= -->
<sect1 id="config.cf.format">
	<title>
	config.cf のフォーマット
	</title>

<para>
config.cf のフォーマットは
	<link linkend="main.cf">
	/usr/local/etc/fml/main.cf
	</link>
と同様です。
<screen>
変数名 = 値

変数名 = 値1 値2 値3

変数名 = 値1
         値2
         値3
</screen>
のようにスペースないしは改行で区切って複数の値を書くことができます。
</para>

<para>
変数定義内での $ による変数の展開も可能です。
たとえば
<screen>
a = 値1
b = $a/値2
</screen>
は最終的に
<screen>
a = 値1
b = 値1/値2
</screen>
と解釈されます。
</para>


<para>
展開は、すべての変数定義を読みこんだ後に行なわれます。
そのため、以下のように定義をすると
<screen>
a = 値1
b = $a/値2/$c
c = 値3
a = 値4
</screen>
すべてを読み込んだあとに解釈されるため
<screen>
b = 値4/値2/値3
</screen>
と解釈されます。
</para>

</sect1>


<!-- ======================================= -->
<sect1 id="config.cf.format.extension">
	<title>
	Postfix スタイルのさらなる拡張
	</title>

<para>
<screen>
変数名 += 値
変数名 -= 値
</screen>
で、特定の値の足し引きができます。
</para>

<para>
<screen>
x  = a b c d
x -= b
</screen>
は
<screen>
x = a c d
</screen>
と解釈されます。
</para>

<para>
また
<screen>
x  = a b c d
x += e
</screen>
は
<screen>
x = a b c d e
</screen>
となります。
</para>

</sect1>


<!-- ======================================= -->
<sect1 id="config.cf.overload">
	<title>
	config.cf の多重読み込み(変数定義の上書き)
	</title>

<para>
複数の config.cf を読み込み、定義の上書きを行なうことができます。
</para>

<para>
これを利用して
『デフォルトの定義』、
『サイト固有の定義』、
『ドメイン固有の定義』
などを別ファイルに分離し、
上書きしつつ多重読み込みをすることができます。
このために、デフォルトでは、いくつかの .cf ファイルに分離されています。
</para>

<para>
&fml8; は起動時にそれらのファイルを順番に読みこみ、
最後にＭＬ固有の config.cf を読み込みます。
そして、すべての設定ファイルを読み込んだ後に変数の展開処理を行ないます。
</para>

</sect1>

<!-- ======================================= -->
<sect1>
	<title>
	展開後に変数を代入すると？
	</title>

<para>
$ をふくむ変数に値の代入が行なわれると、
その場では評価されません。
</para>

<para>
次に、値を取り出すメソッド
   <footnote>
   <para>
   perl の tie() 操作
   </para>
   </footnote>
が呼ばれた際に、初めて変数の再展開が行なわれます。
</para>

<para>
たとえば
<screen>
$config->{ key } = '$ml_home_dir/value';
</screen>
という代入処理が行なわれると、次に
<screen>
$config->{ another_key }
</screen>
(キーはなんでもよい)メソッドが呼ばれた際に、
変数群すべてが再評価されます
(たがいに依存関係があるため、すべての変数が評価されなければなりません)。
</para>


<sect2>
	<title>
	内部構造: 変数展開
	</title>

<para>
少し内部構造の話をします。
</para>

<para>
値の代入操作が行なわれると、
まずは
FML::Config
の内部変数
%_fml_config に、キーと値の組が保存されます。
これは $dir/$file のような代入した値そのままです。
</para>

<para>
FML::Config の get() メソッドは、
%_fml_config ではなく %_fml_config_result の値を返しています。
%_fml_config_result 中の値は $dir などが展開された後の値で、
/var/spool/ml/elena/file などとなっています。
この変数の値の展開は
get() メソッドなど値を取り出すメソッドが呼ばれた際に初めて行なわれます。
</para>

</sect2>

</sect1>


<sect1 id="list.variables.by.alphabeticalorder">
	<title>
	変数一覧 (alphabetical order)
	</title>

&var.table.list.variables;

</sect1>


<sect1 id="list.variables.by.class">
	<title>
	変数一覧 (クラス分類)
	</title>

&var.table.class.variables;

</sect1>


<sect1 id="recipes.internal.config.cf">
	<title>
	レシピ’s	
	</title>

<qandaset>

<qandaentry>

<question>
<para>
config.cf 内で使ってよい関数はどれですか？
</para>
</question>

<answer>

<para>
つまり、フックで利用可能な関数は何ですか？という質問だと思いますが、
公式には「$curproc オブジェクトが提供するメソッド」としておきます。
</para>

<para>
各クラス(e.g. FML::ほげほげ Mail::ほげほげ)に現状実装されているメソッドは、
将来も廃止されないと思いますが、
いちおう
$curproc オブジェクトが提供するメソッドとしておくのが安心だと思います。
</para>

<para>
注意:
&fml4; の設定ファイル config.ph と異なり &fml8; の config.cf では 
=cut より前は変数を書く場所です。
perl の関数を書く場所ではありません。
=cut の後にはフックつまり perl スクリプト を書きます。
</para>

</answer>

</qandaentry>

</qandaset>

</sect1>


</chapter>
