Plan9の配管工

WindowsMacOSでは当たり前なアプリケーションと(データ)ファイルの対応付けについて,UNIXでは統一した仕組みが存在しなかった.例えば,Windowsリポジトリというデータベースにアプリケーションと拡張子の対応付けを持っている.
Plan9では,アプリケーション間でメッセージをやりとりし,さらにメッセージに応じて,設定されたルールに基づいてアプリケーションをディスパッチする仕組みを提供している.これがPlumber,つまり配管工だ.
例えば,シェルで/sys/docをlcすると,PostscriptやPDFファイルがいろいろリスティングされる.その一つにマウスポインタを合わせて,ポップアップメニューから「Plumb」を選択してみよう.page(1)が起動され,選択したドキュメントが表示されるだろう.

ユーザが「Plumb」を選択すると,rioがポインタ位置のテキストをplumber(4)に送信する.plumberはもちろんファイルサーバで,/mnt/plumb/rulesに書かれたルールに基づいて(正確には/user/$user/lib/plumbingが読み込まれた結果が/mnt/plumb/rulesになる),page(1)を起動する.

plumberのインタフェースは/mnt/plumb以下のファイルだ.先に述べたrulesとsend以外はportと呼ばれ,メッセージをアプリケーションに届けるために利用される.アプリケーションがsendファイルにメッセージを書き込むと,plumberがメッセージを仕分けし,対応するアプリケーションにport経由でメッセージを送ることになる.

cpu% cd /mnt/plumb
cpu% lc
edit		msword		postscript	seemail		sendmail
image		none		rules		send		showmail

メッセージのフォーマットはman plumb(2)でわかるが,struct Plumbmsgである.

               typedef
               struct Plumbmsg
               {
                     char      *src;
                     char      *dst;
                     char      *wdir;
                     char      *type;
                     Plumbattr *attr;
                     int       ndata;
                     char      *data;
               } Plumbmsg;

               typedef
               struct Plumbattr
               {
                     char      *name;
                     char      *value;
                     Plumbattr *next;
               } Plumbattr;

これだけで大体わかりそうだが,動作を確認するためのサンプルプログラムを一つ.
次のプログラムを実行すると,edit portをopenし,メッセージの到着をplumbrecvで待つ.後はメッセージの中身をprintしているだけだ.

#include <u.h>
#include <libc.h>
#include <plumb.h>

void 
main(int argc, char **argv)
{
	int fd;
	Plumbmsg *m;

	fd = plumbopen("edit", OREAD);
	if (fd < 0)
		sysfatal("edit");

	while (m = plumbrecv(fd)) {
		print("msg: src='%s' dst='%s' wdir='%s' type='%s' data='", m->src, m->dst, m->wdir);
		write(1, m->data, m->ndata);
		print("'\n");
		plumbfree(m);
	}

	close(fd);
	exits(nil);
}

rioのメニューからソースファイルをplumbすると,acmeが起動されると同時に,次のように出力される.これは,rioからedit portに対して"/usr/oraccha/src/edit.c"というファイル名が送られたと読めばよい.

term% 8.out
msg: src='rio' dst='edit' wdir='/usr/oraccha/src' type='<nil>' data='/usr/oraccha/src/edit.c'

参考文献