だから準備中なんだってば…、書くペース遅いし、無計画に書いてるから支離滅裂だし
ソースはこれ http://www.fenix.ne.jp/cgi-bin/cvsweb.cgi

FENIX BBS System (a.k.a HIME)

■はじめに

その昔、今みたいにインターネットが普及していなかったころ、パソコン通信とよばれる電話回線を使用して、テキストやデータをやりとりする文化がありました。 パソコン通信の世界では、パソコンで用意するソフトウェアは、基本的には、ターミナルソフトだけです。 パソコン通信で使用するターミナルソフトは、TCP/IPのような複雑なプロトコルは使用せず、入力された文字をただ送信、受信した文字をただ表示するだけなので、貧弱なハードウェアでも十分快適に動作します。

さて、時代はインターネットです。 インターネットの特徴として、ひとたびプロバイダにつなげば、世界中どこでもアクセスすることができる、ということがあります。 また、複数のサーバに同時に接続することもできます。 ところが、パソコン通信では、BBSのホストに直接電話回線を接続して通信するため、別のホストにアクセスするためには、一度切断して接続しなおさなくてはなりません。 また、電話回線をインターネットプロバイダへの接続に使用している場合には、パソコン通信を同時に利用することができません。 これでは不便です。
ならば、BBSホスト自体をインターネットから利用できるようにしてしまえばいいのではないか、と考えるのは当然の流れです。

というわけで、インターネットでアクセスできるテキストベースのBBSプログラムを探したのですが、あまり無いんですよ。 世の中BBSというと、Webベースのものを指すようです。
インターネット経由でアクセスできるからといって、WWWベース専用のものにしてしまったのではおもしろくありません。 それに、それは当時、私を含めたFENIXのユーザに多かった、インターネット接続環境をもたないユーザを見捨てることになります。
また、WWW自体がそうであるようにWebベースのBBSは匿名性が高いのに対し、パソコン通信のBBSでは、CUG(Closed User Group)などのように、ユーザ権限を細かく管理し、メッセージの読み書きを制限する特徴があります。
これらパソコン通信のBBSのもっていたアクセス環境や機能を継承しつつ、インターネット経由で利用できるBBSシステムを新規に開発することになりました。 もちろん、せっかく新規に開発するのだから、いままでに無かった、独自の概念を持たせています。

ところで、パソコン通信のようなテキストターミナル用のBBSのことをなんと呼べばいいのでしょう。いまさらですが、以下ではttyベースのBBSということにします。

■FENIX BBS Systemの特徴

■実装概要

FENIX BBS Systemは、ユーザインターフェースはCUIであり、専用shell - fensh - 上でコマンドを入力することによって操作します。
ほとんどのコマンドは、独立したプログラムとして存在し、fenshから実行(fork + execされます。

ユーザが接続、ログイン、コマンド実行までを行なったときのプロセスの流れは以下のようになります。 Process diagram for FENIX BBS System

なぜプログラムが独立しているのか

FENIX BBS Systemでは、各コマンドが独立したプログラムとなっています。 これは見ようによってはリソースの無駄使いのように見え、また、ダサい 構造であることは否めません。しかし、この実装方法には多大なメリットがあり、 また、これ以外の実装方法は困難で面倒です。

プログラムが分かれていることのメリットは、「デバッグが容易」であること、 これに尽きます。 プログラムがわかれていれば、各機能ごとにテストを行うことができます。 そのため、ある機能に関してデバッグをするとき、複数の機能を一つの プログラムにまとめて実装した場合と比べて、遥かに高負荷なテストを行うことが でき、早期にバグを尽きとめられます。 また、運用中に徐々に改良を加えていくことも可能です。実際FENIXでは、 BBSプログラムの改良のためにシステムの停止したことはたぶんありません。 通常運用中にどんどんプログラム入れ替えています。

BBSのデータにアクセスするプログラムは、ルート権限で動かなければなりません。 FENIX BBS Systemでは課金対象ユーザはOSの一般ユーザ権限で実行できる 任意のプログラムを使用することができます。したがってBBSのデータに対し ユーザがBBSプログラム以外を使用して、直接読み書きをすることを回避する 必要があるのです。 そのため、BBSのデータはルート権限のみでアクセス可能とし、一般ユーザが システムのデータにアクセスするとき、つまりメッセージを読み書きするとき には、suidビットの立ったプログラム通してアクセスすることにしました。 むやみにルート権限で動作するプログラムが実行されるのは望ましくありません。 その点でも、各機能ごとにプログラムを分離し、必要のあるコマンドだけが ルート権限で動作することは妥当です。

クライアントサーバ化することはできなかったのか?と思われるかも しれませんが、それは困難なわりにメリットがないと考えました。 単純にソケットを使用してメッセージをやり取りしたのでは、ユーザ権限を 正確にコントロールすることはできません。 なぜならば、サーバプログラムからは、接続してきたクライアントのユーザ名を 正確に知ることができないからです。リクエストを出しているユーザを知るために そのソケットにユーザ名を流したのではは意味がありません。 FENIXでは一般ユーザが自由にプログラムを書くこともできるため、 嘘のユーザ名でリクエストを出すことができてしまうからです。 ここでユーザ名に加えてパスワードも流し、認証処理を行うことで、ユーザを 決定することも可能ですが、それではユーザにもう一度パスワードの入力を 要求することとなりスマートではありません。

■基本概念

ユーザIDとハンドル

FENIX BBS systemでは、ユーザの識別名として、user ID, handle名、alias の3種類を使用できます。 ほぼすべてのコマンドで、これらのどの識別名を使用した場合にも同様の結果が得られますが、一部に例外があります。
User ID
ユーザ登録するときに割り当てられる名前で、ユーザが変更することはできません。
主にlogin時に使用します。逆に、login時に使用できる識別名はUser IDのみです。
システムの内部的には、unixのlogin名そのものです。
handle名
FENIX BBS system内部のみで有効なニックネームで、日本語も使用可能です。
ユーザによる変更が可能です。
alias
主にインターネットメールに使用するニックネームで、ユーザが自由に変更できます。
インターネットネームで使用することを考慮して、半角英数と記号のみが使用可能です。

ユーザ権限

各ユーザには、1-9までのユーザレベルと、所属グループが与えられ、それにより ユーザの実行可能なコマンド、読み書きできるメッセージなどが制限されます。 コマンドの実行制限はシェル(fensh)が、メッセージに対するアクセス制限は、 BBS部(HIME)のライブラリが行います。

■BBS部(HIME)

FENIX BBS systemのBBS部は、HIME - HIerachal MEssage system とよばれ、 その名の通り、メッセージが階層化されて格納されます。 この階層化構造こそが、HIMEのもっとも特徴的な部分です。

HIME message tree

レベルによるメッセージのアクセス制限

FENIX BBS Systemでは、ユーザは1-9までのレベルを持ちます。 ユーザは メッセージを書きこむとき、そのユーザのレベルまでの任意の 読み出し・書きこみレベルを書きこむメッセージに与えることができます。
メッセージのレベルは、そのメッセージへのユーザの読み書きを制限します。
read level
メッセージのレベル <= ユーザレベル のとき、そのメッセージを読むことができます。
メッセージのレベル > ユーザレベル のとき、そのメッセージを読むことはできません。
write level
メッセージのレベル <= ユーザレベルのとき、そのメッセージへレスを書きこむことができます。
メッセージのレベル > ユーザレベル のとき、そのメッセージにレスを書きこむことはできません。

groupによるアクセス制限とCUG(Closed User Group)

FENIX BBS Systemのユーザは一つ以上のgroupに属します。 この、groupはUNIXのgroupと同一のものです。 ユーザは、メッセージを書きこむときに、そのユーザの所属しているグループのうちの一つを、そのメッセージのグループとして指定することができます。 また、そのとき、属性として、openまたはclosedを指定することができます。 メッセージのグループは書きこみを制限し、その属性は読み出しを制限します。 これらの性質を使用し、特定のメッセージ以下のツリーを、CUG(Closed User Group)とすることができます。
CUGとしたい先頭のメッセージに、closed属性を与えるだけで、そのメッセージのグループと同じgroupに所属しているメンバーからしか読み書きできないCUGとなります。
(注:CUGというのは、パソコン通信のBBSにあった、特定のグループにしか読み書きできないボードのことです)

アクセス制限の継承

階層化構造に従い、メッセージのアクセス制限は継承されます。 ユーザがあるメッセージのread level, groupによってアクセスが禁止された場合、そのメッセージの下にあるメッセージアクセスすることはできません。 また、読み出しを制限されているメッセージに書きこむことはできません。 これらの性質を利用することにより、特定のメッセージスレッド全体のアクセス制限を変更したいときに、先頭のメッセージの属性を変更するだけで済むことになります。

ボード

BBSシステムは一般に、大まかな話題毎にボードという単位で分類してメッセージを 格納します。HIMEにもボードと呼ばれる概念は存在しますが、他のシステムとは 若干扱いが異なります。 HIMEの場合、すべてのメッセージがルートメッセージから始まる木の枝として 格納されていくという特徴を持つため、ボードとメッセージの関係は既存のBBSとは 異なります。 HIMEでは、ボード名はそのボードの先頭メッセージのエイリアス名に 過ぎません。したがって、全てのメッセージがボードになりえます。
ある特定のメッセージにボード名をつけたとき、そのメッセージから始まる メッセージツリーがボードとなり、階層化構造にしたがって、 そのメッセージの下に続くメッセージの集合がそのボードに書きこまれた メッセージになります。
既存のBBSと同じ捕らえ方をすると、HIMEでは、ボードはルートメッセージから始まる ツリー1つだけということになってしまいますが、実際にはボードの下にさらに ボードが存在する構造である点に注意してください。message #55, #57

■プログラムセット

FENIX program set
ファイル名 FENSH上の名前 機能
2ndlogin なし 自前のutmpへlogin/logout情報を書き込む
fenlogin なし ユーザ認証処理
fenchat chat チャット
fenedit edit テキストファイルエディタ
fenid id ユーザ情報編集
fenlast last login記録表示
fenmail mail mailインターフェース
fenprof prof profile 表示/編集
fentel telegram 電報
fenwho who ログイン状況表示
goodbye goodbye 遺言メッセージ処理
hime read,news,tree,list,search BBS関連ユーザインターフェース
fensh ( ) 専用shell
fenixuserconfig なし ユーザ情報テーブルを 元にOSの設定ファイルを更新
members なし cgi用ユーザリスト表示
pppstart なし 動的にIPアドレスを割り当てるpppd wrapper

2ndlogin

ユーザのログインシェルとして起動され、forkしてfenshを起動し、 ログイン中は常駐しつづけます。 起動時と終了時に、自前の接続記録ファイル(fenutmp)へ login/logout情報を 書き込みます。また、このとき、名前の逆引きも行います。

2ndloginが行っている処理は、本来、gettyやtelned, sshdが行うべき処理です。 やっていることはlogin/logoutを記録しているだけなので、普通はOSのutmpファイルに保存されているもので間に合うはずです。 2ndloginが必要となった背景は2つあります。

実は今となってはこれら2つの要求では2ndloginの必要性を説明できません。 utmpのホスト名フィールドは256バイトに拡張されたし、日本語変換はライブラリで 行うようになったからです。
しかし、いまのところ2ndloginは残していくつもりです。 いまでも、以下の利点があるからです。

fenlogin

OSの/bin/login同等のユーザ認証処理を行います。 ただし、telnetのように盗聴されるおそれのあるプロトコルで接続してきた場合、 plain passwordを受け付けず、s/keyのチャレンジ/レスポンスを要求します。 また緊急用に、2ndloginではなく、tcshを直接起動する裏口を用意してあります。

fenchat

パソコン通信的なBBSでは必須とも言えるチャット機能です。 IRCクライアントとして実装されています。 動作のためにはIRCサーバをホストで動かす必要があります。

fenedit

テキストファイルエディタです。 行入力志向で、いわゆるスクリーンエディットはできません。

fenid

fenlast

login記録表示

fenmail

インターネットメールにも対応した、mailインターフェースです。 日本語を正しく扱えます。 MIME multipartには受信のみ対応しています。

fenprof

profile 表示/編集

fentel

電報

fenwho

ログイン状況表示

goodbye

ログアウト時に表示される1行のメッセージの表示と編集を行います。

hime -- read,news,tree,list,search

BBS関連ユーザインターフェース

fensh

専用shell

fenixuserconfig

ユーザ情報テーブルを元にOSの設定ファイルを更新

members

cgi用ユーザリスト表示

pppstart

限られたグローバルIPアドレスを有効に利用するため、PPPに割り当てる アドレスを動的に決定します。グローバルIPの数が電話回線の数より少ない 場合に有効です。 将来への布石のつもりで実装しましたが、同時に張られるPPPのセッション数が 多くないので、あまり活躍していません。

■日本語入出力

FENIX BBS Systemではユーザのターミナルで使用する文字コードとして、 sjis,euc,jisのどれでも使用可能です。 内部処理で使用するコードはeucで統一してあり、ターミナルの文字コードとは 分離しています。そのため、入出力のときに文字コードを変換することになります。

現在の実装では、日本語コード変換はライブラリで行っています。 また、ライブラリ内の行入力関数は日本語に対応した行編集機能を持っています。 以前は、OpenBSDのttyドライバを日本語対応化改造したり、 pseudo terminalを使用して日本語変換機能付仮想ターミナルを 作ったこともありましたが、どれも今一つよい結果が得られませんでした。 いろいろな日本語コードで行編集が安定してでき、かつ、一括アップロードで 大量の文字列を流してもおかしくならないようにすることがどうしても うまくできなかったのです。

ライブラリとして実装したことにより、FENIX BBS Systemは安定した日本語コード 変換付入出力ができるようになりました。 また、将来この機能を独立したライブラリとしてexportできる可能性を 得たことになります。 (ほら、パソ通的なBBSって近い将来絶対消えるでしょ。それでもさ...)

■ライブラリ

各コマンドで頻繁に使用する機能をライブラリとしてまとめています。 大まかに以下に分類されます。

ユーザ情報管理
ログイン、ログアウト管理
ユーザID、エイリアス名、ハンドル名の関連付け
端末入出力
漢字コード変換付入出力
日本語対応行編集入力
その他
電報
プロセス名変更
high level BBSアクセス
読み書き
メッセージ検索
low level BBSアクセス
メッセージ間、親子検索
アクセス権チェック

■歴史

1998/3/27 FENIX仕様決定
FEZ,thomasが徹夜で飲みながら仕様を決定
1998/3/28
開発開始
1998/4/*
某工研内に設置したmanamiでプロトタイプ起動開始
1998/6/*
OCN開通に伴い、テスト運用開始
1998/6/*
ソース管理にCVS導入
1998/10/1
CVSリポジトリ再構築
1998/10/16
WEB対応。但し読み出しのみ
1998/10/25
リアルタイム電報機能。たとえ外部コマンドを実行中でも電報が受信可能
1998/10/29
guestログ記録
1998/11/10
自分のユーザレベルを得る関数の高速化。というよりバグで本来の速度がでていなかった。
1998/11/27
goodbyeに編集機能を追加
1998/12/02
PPPのアドレスを動的にマッピングするラッパプログラムを追加
1999/01/19
pseudo-ttyを使用した漢字コード変換機能付ユーザレベル端末ドライバを実装
1999/03/08
CVSリポジトリをkanaに移動
1999/03/08
GNU readlineライブラリに独自の半角かな対応化パッチを当てて利用開始
1999/03/15
fenmailをPOP経由でなく直接スプールにアクセスするようにした
1999/03/15
fenshから任意の外部コマンドを直接実行可能にした。一般的なSHELLにより近く。
1999/05/12
独自の日本語対応入出力ライブラリを開発(jgetline, jfprintf)。

FENIX/ MEMBERS/ thomas's HOME/ MEMO/ fenix

佐藤益弘 thomas@fenix.ne.jp