Wikifs

Plan9ではWikiもファイルサーバとして実装されている.これがwikifs.設定の仕方はInformal Wiki Setupやman wikifs(4)が参考になる.このページの通りに設定したら,Linux側からhttp://172.20.0.2/wiki/sample/plan_9_wiki/にアクセスすればよい.

wikifsは指定されたWikiデータに対するファイルシステムインタフェースを提供する.通常は,httpd経由でHTMLを出力するが,acmeWikiエディタとして利用するためにプレーンテキストを出力するインタフェース*1も持つ.今回は前者にしぼって話をする.

まず,wikifsを実行する.以下の説明では,ディレクトリ/sys/lib/wiki.sampleにWikiデータがあると仮定して話を進める.-sオプションはサービス名で,-pオプションはパーミッションの指定.この例では,/srv/wiki.sampleをパーミッション0666でオープンして,(httpdと通信するための)ファイルディスクリプタをポストする.-aオプションはacmeと通信するために9Pコネクションを使うためのオプションなので,Webページとして使うだけなら省略してもよい.

wikifs -p 666 -s wiki.sample -a tcp!*!wiki /sys/lib/wiki.sample

続いて,httpdを起動する.httpdは起動時に/lib/namespace.httpdの定義にしたがって名前空間をセットアップする.Plan9名前空間はプロセスごとに独立なので,httpd名前空間を動作に必要な部分だけに絞りこむことができる.Wikiに関する記述は次のmountで,/usr/web/wiki/sampleに*2,さきほどwikifsが作った#s/wiki.sampleをユニオンマウントしている.

mount -b #s/wiki.sample /usr/web/wiki/sample

例えば,http://172.20.0.2/wiki/sample/plan_9_wiki/というURLにアクセスした場合*3httpdは#s/wiki.sample/plan_9_wiki/にアクセスすることになる.そして,httpがこのファイルをopen,readすると,wikifsの処理が始まる.wikifsは/sys/lib/wiki.sample/d/mapファイルを参照し,plan_9_wikiがd/1にマップされているので,d/1をパーズして,HTML表現に変換し,writeする.その出力をhttpdがreadし,ネットワークに出力する.

/sys/lib/wiki/sample/d/map:
0 wiki syntax
1 plan 9 wiki
2 sandbox
3 supported pc hardware

plan_9_wikiに対する編集はplan_9_wiki/edit.html,差分はplan_9_wiki/diff.htmlなどになる.このようにURL的には1 wikiページはディレクトリとして見えるが,実装は1 ファイルとなる.Wikifsの役割は,このようなリソースに対するマッピングの変換だと言える.なお,/usr/web/wiki/sampleにはcreate.htmlしかファイルがなく,edit.htmlなど他のHTMLファイルは/sys/lib/wiki.sampleディレクトリにある.edit.htmlなどは一種のテンプレートファイルで,PAGEと書かれている部分は,plan_9_wiki/edit.htmlの場合であれば,plan_9_wikiの内容に展開される.

/sys/lib/wiki.sample/edit.html:
<html>
<head>
<title>TITLE (Editing DATE version)</title>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<!-- FFFFE9 is acme yellow; FFFFD0 is as close as
 you can get to it before charon decides to use
 grey instead of map entry 254 -->
<body bgcolor="#FFFFD0" link="#0000AA" alink="#0000AA" vlink="#0000AA">
<center>
<font size=+2><b>TITLE</b></font> (Editing DATE version)
</center>
<p>

For information on editing, see the
description of
<a href="../0">Plan 9 wiki syntax</a>.
<p>
<form action="/magic/wikipost" method="post">
<table><tr><td valign=top>
<input type="submit" name="x" value="Put"></td><td>
<table>
<tr><td align=right>(optional) Comment:</td><td><input type="text" name="comment" value="" cols=40></td></tr>
<tr><td align=right>(optional) Email:</td><td><input type="text" name="author" value="" cols=40></td></tr>
</table>
<input type="hidden" name="title" value="TITLE">
<input type="hidden" name="version" value="VERSION">
<input type="hidden" name="service" value="sample">
<input type="hidden" name="base" value="/wiki/sample">
<p>
<textarea name="text" wrap="virtual" cols="80" rows="25">
PAGE
</textarea><p>
</td>
</table>
</form>

<hr>
<table width=100%><tr>
<td valign=center align=left>
</td><td valign=center align=right>
<a href="../about.html">About the server</a>
|
<a href="http://plan9.bell-labs.com/plan9"
><img src="http://plan9.bell-labs.com/plan9/img/power36.gif"
alt="Powered by Plan 9"></a>
</td>
</tr></table>
</html>
</body>

edit.htmlで気になるのは,次のPOSTメソッドの部分だろう.

<form action="/magic/wikipost" method="post">

httpdはPOSTメソッドを処理するために,wikipostというヘルパープログラムを使う.URLが"/magic/"で始まる場合は,それに続くプログラムをexeclして処理する(rforkはしないので,execlに失敗しない限り,httpdに処理が戻ってくることはない).Plan9には動的ロードがないので,プラグイン的な仕掛けを作るためにこのようにしているのだろう.

*1:acmeを外部エディタとして利用するイメージ

*2:デフォルトのサーバルートディレクトリは/usr/webになる.

*3:http://172.20.0.2/wiki/sample/1/でも結果は同じ.つまり,plan_9_wikiは1のエイリアスである.このマッピングが記述されているのがd/mapファイル.