proftpd は比較的軽量で、スタンドアローンでも(x)inetd配下でも動くftpdである。しかも、apache httpdに似たモジュールによる機能追加をサポートしており、コンフィグレーションファイルの書き方も似ている。ftpについて理解していてApache httpdの管理経験があれば、特にドキュメントを読まなくても一通りのことはできる。もちろんmod_tlsでSSLには対応済み。ただし、Explicit のみ。
ApacheのようなDSOに対応していないのが弱点で、つまりモジュールを足すには再コンパイルするしか無かった。でも、なんか1.3.0を見るとmod_dsoというモジュールが追加になっているので解消された模様。
というわけで、そんなproftpdのモジュールを開発してみようと思う。本稿はその開発メモである。
staticモジュール
とりあえず、staticモジュールを作るのを目標としよう。
Make段階でmodules/glue.shというスクリプトが走って、これがmodules/mod*.cから、モジュール定義構造体(typedef module_struc module)へのポインタを抜き出す。だから、staticリンクされるモジュールでは、 modules/modモジュール名.c というファイルに module型のグローバル変数 "モジュール名_module"を定義すればよい。そうすれば勝手に、staticロードモジュールリストにリストアップされる。
in mod_example.c
#include "conf.h" module example_module = { /* module構造体の双方向リンクリストのためのポインタ。実行時に使われるのか? */ /* .next = */ NULL, /* .prev = */ NULL, /* 準拠しているProftpd Module APIのバージョン。モジュール自体のバージョンではない */ /* .api_version = */ 0x20, /* モジュール名 */ /* .name = */ "example", /* このモジュールが提供するディレクティブの定義テーブルへのポインタ */ /* .conftable = */ NULL, /* このモジュールが提供するコマンドハンドラの定義テーブルへのポインタ */ /* FTPコマンドの実行に割り込むにはこれを使うってことか。 */ /* .cmdtable = */ NULL, /* おなじく、認証処理への割り込みのためのハンドラ定義テーブル */ /* .authtable = */ NULL, /* モジュール初期化関数へのポインタ */ /* .init = */ example_init, /* FTPセッション初期化関数へのポインタ */ /* .sess_init = */ example_sess_init, /* モジュールのバージョン文字列 */ /* .module_version = */"mod_example/example", /* よく分からない。NULLで良いっぽい */ /* .handle = */ NULL, /*" Internal Use"と書いてある。実行時の優先順位か? */ /* .priority = */ 0 };
提供しない部分はNULLで良いらしい。example_module変数は定義テーブルって言う性質上constにしたいような気もするけれど、あからさまに実行時にリンクリスト作るぞーって感じだからそれは無理だろう。constにしたらアーキテクチャにもよるけど、たぶんSEGVる。