FreeBSD Handbook を元に自分自身を書き換える fastest_cvsup

FreeBSDports に、fastest_cvsup というものがある。(sysutils/fastest_cvsup).


公開されているいくつかの CVSup サーバに接続を試みて、その時間を計り、もっとも速く接続することができるホストの名前を表示してくれるというプログラム。


世の FreeBSD ユーザは、自分の FreeBSD のソースツリー (/usr/src/ 以下) を最新にするときや、ports tree (/usr/ports/ 以下) を最新にする場合に cvsup, csup, portsnap などのコマンドを使うのだが、それらのコマンドに対して CVSup のサーバを指定してあげる必要がある。 fastest_cvsup が教えてくれるホストを指定してあげれば、割とすいているとか、ネットワーク的に近いサーバを使うことが出来るようになる。


CVSup のサーバ一覧は、ここで公開されている。(サーバ一覧はリンク先ページの下のほう):

FreeBSD Handbook - A.5 Using CVSup
http://www.freebsd.org/doc/en/books/handbook/cvsup.html


実はこの URL は、fastest_cvsup のプログラム内にハードコードされている。


fastest_cvsupPerl で書かれており、接続を試みる CVSup サーバのリスト(を作り出すためのデータ)がリストとして書かれているのだが、そのほかに、こんな行が中にあるのだ。

# The URL to connect to when remotely fetching a list of CVSup servers:

my $URL="http://www.freebsd.org/doc/en/books/handbook/cvsup.html";


このプログラムには、FreeBSD ハンドブックの「A.5 Using CVSup」のページをネット経由で取得して、その記述から公開されている CVSup サーバのリストを得る機能が付いている。リストを得るだけじゃなくて、そのリストを元に、自分自身を書き換える。


以下は、自分自身を置き換えている部分:

          # write it out to a new file

          open(NEW, "> $0.new") or die "Error, can't open $0.new: $!";
          print NEW $bigstring or die "Error, can't write $0.new: $!";
          close(NEW) or die "Error, can't close $0.new: $!";

          # swap them over

          rename($0, "$0.orig") or die "Error, can't rename $0 to $0.orig: $!";
          rename("$0.new", $0) or die "Error, can't rename $0.new to $0: $!";


変数 $0 は、Perl の定義済み変数で、プログラム名が入っている。 $bigstring には、自分自身のコピー(ただし、サーバ一覧のリストだけは最新のものに更新されているもの)が入っている。


この機能を使うには、まず su して、プログラム内の $REWRITE_SELF = 0;$REWRITE_SELF = 1; に書き換え、さらに -r オプションつきで起動する。