sendmail の設定で、sendmail.mc から sendmail.cf を作成する場合に利用するのが
GNU m4 マクロプロセッサです。これには、マニュアルの日本語訳があります。
このシステムの GNU m4 は、Ver. 1.4.4 です。
m4 は、「1. 序論」にも書いてあるとおり、深入りすると健康をそこなうおそれがあるようですから、深入りせず sendmail で利用する機能に絞って、忘れないように調べてみます。
m4 は、入力をトークンに分割して処理するので、入力トークンの種類を見てみます。
さらに、コメントが次のように定義されています。
# と「改行文字」で区切られた部分で、その部分は何も処理されず、そのまま出力されます。
あとは、マクロの使い方を覚えるだけです。マクロは組み込みマクロとユーザ定義マクロがあります。m4 を使うには、このマクロ定義を行って、入力を変換して出力とすればよいわけです。ユーザ定義マクロの定義の方法ですが、
のようにdefineマクロを使います。これで、name が expansion に展開されるよう
に定義されます。defineによるマクロ定義は出力されませんが、最後の改行文字は定義外ですのでそのまま出力されます。引数は、$1, $2 のように参照できます。
さて、マクロの呼び出しですが、
のようになり、name と ( の間は空けてはいけない決まりです。
・マクロ呼び出しで展開されて、再びマクロが現れたらもう一度そのマクロを呼び出します。
・マクロの引数がマクロなら、先にそのマクロを呼び出します。
・引数なしマクロを連続して展開し連結するなら、マクロ名の間は `' (空のクォートされた文字列)を挿入します。
また、空白文字に非常に敏感です。たとえば引数の前にある空白文字は無視されますが、引数の後ろの , までの空白文字は意味があります。また、引数の前なら改行文字があっても空白文字と同じに扱われるようです。つまり、マクロ定義中に改行可能です。
組み込みマクロの多くは、引数がないとマクロとみなされません。その場合は、そのまま出力されます。
名前の全部または一部をクォートすると、マクロとみなされなくなります。つまり展開されず、そのまま出力されます。
これで、m4 の説明はおしまいです。
さて、sendmail.mc の場合は、組み込みマクロ divert と dnl を知っておく必要があります。
dnl マクロは、最初の改行文字までにある文字をすべて捨てて出力しません。従って、
とすると、この行はまったく出力されず、先ほどの説明どおり後ろのdnl がなければ空行が出力されます。
divertマクロは、sendmail.mc の場合、sendmail.mc 自身のコメントを挿入するのに使います。
とすれば、これらすべてが出力されません。
m4 の実行は単純で、入力ファイルが test.mc だとすると、以下のようになります。
標準出力に出力結果が出てきます。ためしにサンプルを作ってみます。
divert や dnl や macro 定義、参照が分かったでしょうか。
sendmail の cf/cf/Build は、
です。OSTYPE とか、DOMAIN とかの mc ファイルの指定は、定義されたマクロであり、その定義は、cf/m4/cf.m4 から読み込まれる cf/m4/cfhead.m4 で行われています。
cf/m4/cfhead.m4 をチラッと見たところ、
OSTYPE は、cf/ostype 内の引数で指定された名前の .m4 ファイルを、
DOMAIN は、cf/domain 内の引数で指定された名前の .m4 ファイルを、
FEATURE は、cf/feature 内の引数で指定された名前の .m4 ファイルを、
MAILER は、cf/mailer 内の引数で指定された名前の .m4 ファイルを、
を展開するようです。
今後は、m4 を使って sendmail.mc から semdmail.cf を作成していろいろ調べたいと思います。
GNU m4 マクロプロセッサです。これには、マニュアルの日本語訳があります。
このシステムの GNU m4 は、Ver. 1.4.4 です。
m4 は、「1. 序論」にも書いてあるとおり、深入りすると健康をそこなうおそれがあるようですから、深入りせず sendmail で利用する機能に絞って、忘れないように調べてみます。
m4 は、入力をトークンに分割して処理するので、入力トークンの種類を見てみます。
・ 名前: _ または英文字で始まる、 _ または英数字の文字列。 マクロ名かどうかはマクロ定義があるかどうかだけです。 ・ クォートされた文字列: 引用符 ` と ' (back quote,quote) のペアで囲まれた文字列で、一番外側のペアだけが有効です。 ・ その他: 上記2つ以外のすべての文字です。
さらに、コメントが次のように定義されています。
# と「改行文字」で区切られた部分で、その部分は何も処理されず、そのまま出力されます。
あとは、マクロの使い方を覚えるだけです。マクロは組み込みマクロとユーザ定義マクロがあります。m4 を使うには、このマクロ定義を行って、入力を変換して出力とすればよいわけです。ユーザ定義マクロの定義の方法ですが、
define(name[, expansion])
のようにdefineマクロを使います。これで、name が expansion に展開されるよう
に定義されます。defineによるマクロ定義は出力されませんが、最後の改行文字は定義外ですのでそのまま出力されます。引数は、$1, $2 のように参照できます。
さて、マクロの呼び出しですが、
name 引数なしの呼び出し name(arg1, arg2, ... , argN) N個の引数を伴った呼び出し name() 空の文字列を1つだけ引数とする呼び出し
のようになり、name と ( の間は空けてはいけない決まりです。
・マクロ呼び出しで展開されて、再びマクロが現れたらもう一度そのマクロを呼び出します。
・マクロの引数がマクロなら、先にそのマクロを呼び出します。
・引数なしマクロを連続して展開し連結するなら、マクロ名の間は `' (空のクォートされた文字列)を挿入します。
また、空白文字に非常に敏感です。たとえば引数の前にある空白文字は無視されますが、引数の後ろの , までの空白文字は意味があります。また、引数の前なら改行文字があっても空白文字と同じに扱われるようです。つまり、マクロ定義中に改行可能です。
組み込みマクロの多くは、引数がないとマクロとみなされません。その場合は、そのまま出力されます。
名前の全部または一部をクォートすると、マクロとみなされなくなります。つまり展開されず、そのまま出力されます。
これで、m4 の説明はおしまいです。
さて、sendmail.mc の場合は、組み込みマクロ divert と dnl を知っておく必要があります。
dnl マクロは、最初の改行文字までにある文字をすべて捨てて出力しません。従って、
define(`x', `expansion')dnl
とすると、この行はまったく出力されず、先ほどの説明どおり後ろのdnl がなければ空行が出力されます。
divertマクロは、sendmail.mc の場合、sendmail.mc 自身のコメントを挿入するのに使います。
divert(-1) 複数行のコメント ......... divert(0)dnl
とすれば、これらすべてが出力されません。
m4 の実行は単純で、入力ファイルが test.mc だとすると、以下のようになります。
$ m4 test.mc
標準出力に出力結果が出てきます。ためしにサンプルを作ってみます。
$ cat test.mc divert(-1) # TEST LINE No.1 # TEST LINE No.2 divert(0)dnl test1 test2 dnl test3 test4 test5 test6 test7 define(`x',`expansion')dnl define(`y',`dnl') test8 x test9 test10 y test11 $ m4 test.mc test1 test2 test6 test7 test8 expansion test9 test10 test11 $
divert や dnl や macro 定義、参照が分かったでしょうか。
sendmail の cf/cf/Build は、
/usr/bin/m4 ../m4/cf.m4 sendmail.mc > sendmail.cf
です。OSTYPE とか、DOMAIN とかの mc ファイルの指定は、定義されたマクロであり、その定義は、cf/m4/cf.m4 から読み込まれる cf/m4/cfhead.m4 で行われています。
cf/m4/cfhead.m4 をチラッと見たところ、
OSTYPE は、cf/ostype 内の引数で指定された名前の .m4 ファイルを、
DOMAIN は、cf/domain 内の引数で指定された名前の .m4 ファイルを、
FEATURE は、cf/feature 内の引数で指定された名前の .m4 ファイルを、
MAILER は、cf/mailer 内の引数で指定された名前の .m4 ファイルを、
を展開するようです。
今後は、m4 を使って sendmail.mc から semdmail.cf を作成していろいろ調べたいと思います。
※コメント投稿者のブログIDはブログ作成者のみに通知されます