天泣記

2006-10-02 (Mon)

#1 [dhcp] ARPCHECK, ARPSEND [CODE blog]

PREINIT の次は ARPCHECK, ARPSEND である。

dhcp-3.0.4/client/scripts/linux:103-105

103: if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
104:   exit_with_hooks 0
105: fi

なにもしないんで、とくにいうことはない。

いや、いまふと思い付いたが、exit_with_hooks の中で reason を変更すると他の reason に対する動作を起動できるな。だからといってうれしかったりかなしかったりするいかというと謎だが。

2006-10-03 (Tue)

#1

生産性は計測不能」を読み返す。

#2 [dhcp] BOUND, RENEW, REBIND, REBOOT [CODE blog]

次はちょっと長い。

dhcp-3.0.4/client/scripts/linux:107-151

107: if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
108:    [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
109:   current_hostname=`hostname`
110:   if [ x$current_hostname = x ] || \
111:      [ x$current_hostname = x$old_host_name ]; then
112:     if [ x$current_hostname = x ] || \
113:        [ x$new_host_name != x$old_host_name ]; then
114:       hostname $new_host_name
115:     fi
116:   fi
117:
118:   if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
119:                 [ x$alias_ip_address != x$old_ip_address ]; then
120:     # Possible new alias. Remove old alias.
121:     ifconfig $interface:0- inet 0
122:   fi
123:   if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
124:     # IP address changed. Bringing down the interface will delete all routes,
125:     # and clear the ARP cache.
126:     ifconfig $interface inet 0 down
127:
128:   fi
129:   if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
130:      [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
131:
132:     ifconfig $interface inet $new_ip_address $new_subnet_arg \
133:                                                         $new_broadcast_arg
134:     # Add a network route to the computed network address.
135:     if [ $relmajor -lt 2 ] || \
136:                 ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
137:       route add -net $new_network_number $new_subnet_arg dev $interface
138:     fi
139:     for router in $new_routers; do
140:       route add default gw $router
141:     done
142:   fi
143:   if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
144:    then
145:     ifconfig $interface:0- inet 0
146:     ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
147:     route add -host $alias_ip_address $interface:0
148:   fi
149:   make_resolv_conf
150:   exit_with_hooks 0
151: fi

まず最初はホスト名の設定である。

dhcp-3.0.4/client/scripts/linux:109-116

109:   current_hostname=`hostname`
110:   if [ x$current_hostname = x ] || \
111:      [ x$current_hostname = x$old_host_name ]; then
112:     if [ x$current_hostname = x ] || \
113:        [ x$new_host_name != x$old_host_name ]; then
114:       hostname $new_host_name
115:     fi
116:   fi

とりあえず、あいかわらずクォートしてない。 current_hostname=`hostname` とか x$current_hostname = x とやっている。まぁ、代入のところは問題ないが、展開の所は field splitting や pathname expantion が起こるというのに。hostname の結果に空白やグロブ文字が入ることを考えていないのだろうか?まぁ、普通考えないか。

それで、[ x$current_hostname = x ] || [ x$current_hostname = x$old_host_name ] という条件で (おそらく) ホスト名が dhcp の管理下にあって手動で設定されていないことを確認し、 [ x$current_hostname = x ] || [ x$new_host_name != x$old_host_name ] という条件で設定が必要だったら設定しているという意図が感じられる。この [ x$current_hostname = x ] という条件は外側の条件にも入っているので、これは、$current_hostname が空だったら有無をいわさず設定することになる。

次は、alias の設定である。

dhcp-3.0.4/client/scripts/linux:118-122

118:   if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
119:                 [ x$alias_ip_address != x$old_ip_address ]; then
120:     # Possible new alias. Remove old alias.
121:     ifconfig $interface:0- inet 0
122:   fi

ここはまじめに読んでもしかたないと結論したので気にしないことにする。

次が IP アドレスが変わったときのインターフェースの後始末である。

dhcp-3.0.4/client/scripts/linux:123-128

123:   if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
124:     # IP address changed. Bringing down the interface will delete all routes,
125:     # and clear the ARP cache.
126:     ifconfig $interface inet 0 down
127:
128:   fi

down しておく、というのが意図であろう。 $interface がクォートされていないのは置いておくとすると、 inet 0 と指定しているのはなんでだろう? up/down って、インターフェース毎の属性じゃなかったか? inet だけ、とかあったっけ? それとも inet と書かないとうまくいかないとかあるのか?

後始末したので次は新しい IP アドレスなどの設定である。

dhcp-3.0.4/client/scripts/linux:129-142

129:   if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
130:      [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
131:
132:     ifconfig $interface inet $new_ip_address $new_subnet_arg \
133:                                                         $new_broadcast_arg
134:     # Add a network route to the computed network address.
135:     if [ $relmajor -lt 2 ] || \
136:                 ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
137:       route add -net $new_network_number $new_subnet_arg dev $interface
138:     fi
139:     for router in $new_routers; do
140:       route add default gw $router
141:     done
142:   fi

まず ifconfig で IP アドレスを設定し、route でルーティングを設定している。

ここでクォートしてないのが気になるが、$new_subnet_arg や$new_broadcast_arg は意図的かもしれない。これらは netmask 255.255.255.0 とか複数の引数になるのであろうから、 field splitting を適用する必要があるのは想定できる。

しかし、$new_subnet_arg にそういう "netmask" とかの文字列を入れるのはいかがなものであろうか。そこは ifconfig によって違ったりはしないのか?まぁ、そこを変える奴はさすがにいないのかな。

ルーティングの設定は、まず [ $relmajor -lt 2 ] || ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ) という条件で Linux 2.0 以前という条件が成り立てば、 route add -net $new_network_number $new_subnet_arg dev $interface としてローカルネットワークへのルートを設定している。へー、古い Linux は手動で設定しないといけなかったのかな。まぁ、この (あんまり信用できない) スクリプトから読み取れる知識を信用するのはちとなんだが。

その後は $new_routers という変数に複数入っているルータを route add default gw $router として設定している。えーと、デフォルトルートが複数ですか。個人的にはそういう環境は体験したことがないんだけど、それってどう動くんだっけ?

次が alias の設定である。

dhcp-3.0.4/client/scripts/linux:143-148

143:   if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
144:    then
145:     ifconfig $interface:0- inet 0
146:     ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
147:     route add -host $alias_ip_address $interface:0
148:   fi

これは気にしない、と。

最後に resolv.conf を生成する make_resolv_conf を呼び出して exit_with_hooks でおしまい。

dhcp-3.0.4/client/scripts/linux:149-150

149:   make_resolv_conf
150:   exit_with_hooks 0

まぁ、ここの、make_resolv_conf で、(ドメインがないときに) resolv.conf 生成を間違えるわけだ。

2006-10-04 (Wed)

#1

ふと、Google Maps の地図で東京タワーを見た

<URL:http://www.google.co.jp/maps?hl=ja&q=&ie=UTF8&om=1&z=18&ll=35.65863,139.745514&spn=0.001935,0.003626>

この、地図に表示される建物の形というのは、どうやって決まるのだろうか

#2 [gonzui] ファイル名 [CODE blog]

ふと、ファイル名を構成する文字を数えてみる。

まず、codeblog で今まで貯めた tarball のファイル名を全部リストする。

% for f in * do tar tf $f done > ~/0

んで、そのファイルの文字を数える。(改行については気にしない)

% ruby -e ' s = ARGF.read 0.upto(255) {|c|

ch = [c].pack("C")
n = s.count(ch)
puts "#{n} #{ch.dump}" if n > 0

}' ~/0|sort -n

んー、あんまりかっこよくない。でも動くからいっか。

で、結果。

1 "#" 1 "*" 1 "~" 4 "!" 6 "(" 6 ")" 6 "," 8 "{" 8 "}" 76 "@" 87 " " 698 "Y" ... 884151 "t" 1038979 "c" 1087025 "." 1136941 "e" 1242772 "s" 1729378 "/"

"#", "*", "~" が「れあ」らしい。

具体的にはどんなファイルで使われているのだろう。

% grep '[#*~]' ~/0 gcc-1.21/emit-rtl.c~ gdb-6.4/gdb/.#version.in.1.1576.2.32 opensc-0.11.1/doc/api/*/

んー、emacs のバックアップファイルと、cvs の作った奴と、えーと、opensc のはナニ?

gonzui でみると... "emit-rtl.c~" は exclude されててインデクスされてない。 "*" は空ディレクトリでこれも入っていない。 ".#version.in.1.1576.2.32" は、あー、これは URI のエスケープに洩れがあるので修正。

2006-10-11 (Wed)

#1 [codeblog] login-ui.pl [CODE blog]

CODE blog の typekey 認証を自前で行うクライアントを書き、特定の日付の「編集」を行うところに適用した所、ログインした後にどうも目的のページに戻ってこない。

しばらく調べた結果、login-ui.pl の中で = をエスケープすべき所でしていないというバグがみつかった。

% diff -u login-ui.pl.org /var/www/codeblog/login-ui.pl

login-ui.pl.org 2006-10-11 21:54:49.000000000 +0900

+++ /var/www/codeblog/login-ui.pl 2006-10-11 21:57:54.000000000 +0900 @@ -6,7 +6,9 @@

sub escape_uri {
    my ($string) = @_;
    my $r = Apache2::RequestUtil->request;

- return Apache2::Util::escape_path($string, $r->pool);

$r = Apache2::Util::escape_path($string, $r->pool);
$r =~ s/=/%3D/g;
return $r;
}

my $Protected = 'https://www.codeblog.org/login';

うぅむ。ad hoc すぎで正しくないが、とりあえず動く。

これの問題は、用途にあったエスケープ関数を使っていない所である。おそらく。この escape_uri 関数は、以下のように、application/x-www-form-urlencoded の値のところに入れるものに使っている。

$uri = escape_uri("$Protected?destination=" . escape_uri($uri)); ... <a href="$tk_url?t=$token&v=1.1&need_email=0&_return=$uri">Log in via TypeKey</a>

しかし、Apache2::Util::escape_path というのはおそらくなにか違う目的のものなのであろう。

とすると、目的にあった関数に変えるというのが正しいが、さて、その関数はどれだ?

ドキュメントを眺めてみないとな。

2006-10-12 (Thu)

#1 [codeblog] login-ui.pl [CODE blog]

login-ui.pl について新部さんに尋ねた所、これは Apache-AuthTypeKey からもってきたとのことであった。

ただ、ソースをみると、問題の escape_uri を定義する部分はなくて、 escape_uri は Apache::Util のものを使っている。

さらに (新部さんが) 調べた結果、 Apache::Util の escape_uri は mod_perl 1 にはあったが、 mod_perl 2 でなくなり、 Apache2::Util::escape_path をかわりに使うべきということでああった。

<URL:http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache__Util__escape_uri___>

で、www.codeblog.org の mod_perl は mod_perl 2 なので、なくて動かなくてどうにかしなければならず、 escape_uri を escape_path で定義するコードがあって、それをコピペしたのではないかということであった。

とすると、問題を報告するには、mod_perl 1 の escape_uri の挙動をちゃんと確認してからにしないといけないなぁ...

2006-10-13 (Fri)

#1

明日は CodeFest京都2006

一昨日から (ほぼ) 徹夜で作っている wvs (仮称) をいじるか

2006-10-17 (Tue)

#1

楽園通信社綺談が復刻されていたので、とりあえず買ってみる。

まぁ、処分してないはずで家のどこかにはあるはずだが、期待をこめて。

ビブリオテーク・リヴも出るみたいだが、サイズはあのままなのかな?

#2 [tdiary] 本日のリンク元 [CODE blog]

tDiary の「本日のリンク元」には URL が表示されるのだが、長い URL は途中で切られる。

切られるといっても表示するほうであって、リンク自体は切られないのでそこまではいいのであるが、切りかたがよろしくない。

https://www.codeblog.org/blog/akr/20061012.html をみるとわかるが、マルチバイト文字を考えていないようで、文字の中で切っている。

その結果、ページ全体としてエンコーディングが正しくない。

そして、現在作っているツールで、ページを読み込み、内部エンコーディングに変換したときに、正しく変換できているかどうか検査するために round trip するかどうか逆変換すると、 round trip しないので、うまくいかない。

まぁ、外部エンコーディング->内部エンコーディング->外部エンコーディングという round trip は常に成り立つわけではないので、そんな検査をするのが悪いともいえるか?

だが、十分正確に読み込めて変換できたということを確認するにはどうしたらいいだろう。

コード変換に問題が起きるケースとしては、以下のものが考えられる

1. 入力エンコーディングの種別が内容にあっていない
2. 壊れたデータが入っている (今回はこのケース)
3. 入力にある文字が出力エンコーディングで表現できない

1 はまぁ問題であるのだががんばって charset パラメータを世界の津々浦々まで行き届かせるとして、 2, 3 が区別できないのが厄介である。

2 のときは無視して話を進めたいが、 3 のときはユーザにもっとましな出力エンコーディングを指定せよといいたい。

... とすると、十分にリッチなコード (つまり UTF-8) でデコードして失敗したら壊れたデータが入っている、と考えればいいかな。

2006-10-18 (Wed)

#1 [svn] svn で、chroot [CODE blog]

最近、svn を chroot 環境で動かしている。

・ サーバ全体の環境は Debian sarge
・ svn は Debian etch のものを使う
・ svn+ssh によるコミッタのアクセス (公開鍵認証)
・ svn プロトコルによる anonymous アクセス
・ 複数リポジトリのサポート
・ 複数コミッタのサポート
・ リポジトリ毎に uid を割り当てる
・ anonymous アクセスには uid を (全体で) ひとつ割り当てる
・ コミッタ用の URL は svn+ssh://svn-$REPNAME@server.domain/$REPNAME
・ anonymous 用 URL は svn://server.domain/$REPNAME
#2 [svn] サーバ全体の設定 [CODE blog]

まず、root になって、umask をちゃんと設定する。

# umask 022

chrootuid と debootstrap をインストールする。 debootstrap は chroot 環境内に Debian etch 環境を作るのに必要であり、 chrootuid は chroot 環境内に特定の uid で飛び込むために使う。

# apt-get install sudo chrootuid debootstrap

ディレクトリを作る。 root partition 以外に作るのであれば、/svn は適当なシンボリックリンクにする。

# mkdir /svn
# mkdir /svn/home

リポジトリに対する anonymous access を行うユーザを作る。

# adduser --home /svn/home/svnreader --shell /bin/false --disabled-password --gecos 'svn reader' svnreader

/svn/chroot に sarge を install する。 (必要なのは etch であるが、sarge の debootstrap は etch を install できない)

# cd /svn
# debootstrap sarge /svn/chroot ftp://aist.ring.gr.jp/pub/linux/debian/debian

chroot 環境内での shell を起動する。ここで、PS1 によりプロンプトを設定しているのは区別をわかりやすくするためで、 TERM を設定しているのは debootstrap 直後には kterm とかの端末情報がないためである。

# PS1='(chroot)\$ ' TERM=vt100 chroot /svn/chroot /bin/sh

chroot 環境を sarge から etch に upgrade する。

(chroot)# echo deb ftp://aist.ring.gr.jp/pub/linux/debian/debian etch main > /etc/apt/sources.list
(chroot)# echo deb http://security.debian.org/ etch/updates main >> /etc/apt/sources.list
(chroot)# apt-get update
(chroot)# apt-get --download-only dist-upgrade
(chroot)# apt-get dist-upgrade

etch では gpg によるパッケージの検証がおこなわれるので、そのために gnupg をインストールする。その検証のためには、署名に対応する公開鍵を取得して追加する。 (ただ、それが正しい公開鍵であることを確認していないのは問題である。きっと etch が最初からインストールされているときにはそっちからコピーしてくるのがいいのではなかろうか)

(chroot)# apt-get install gnupg
(chroot)# cd /root
(chroot)# wget http://ftp-master.debian.org/ziyi_key_2006.asc
(chroot)# apt-key add ziyi_key_2006.asc
(chroot)# apt-get update

subversion が必要なので install する。

(chroot)# apt-get install subversion

chroot 環境では inetd や atd といったサーバを起動する必要はない。しかし、デフォルトではパッケージをインストールやアップグレードしたときにサーバが起動してしまう。それを抑止するため、/usr/sbin/policy-rc.d に exit 101 するだけのファイルを作る。また、(sarge から引き継がれる) netkit-inetd は policy-rc.d を見ないようなので、 openbsd-inetd をインストールする。

(chroot)# cat <<'End' > /usr/sbin/policy-rc.d
#!/bin/sh
exit 101
End
(chroot)# apt-get install openbsd-inetd

chroot 環境から出る。

(chroot)# exit

ここまでで作った etch の chroot 環境のさらに中に、 subversion サーバを動かすためだけの小さな chroot 環境を作る。

まず、ディレクトリを作る

# mkdir /svn/chroot/chroot-repo
# mkdir /svn/chroot/chroot-repo/repo

次に必要なファイルをコピーするわけであるが、このコピーは etch な chroot 環境を upgrade するたびに行う必要があるので、 copy-files というスクリプトにしてまとめる。そのスクリプトを以下のようにして作る。 (このファイルのリストは、IA-64 なところとか、環境に依存している)

# cat <<'End' > copy-files
#!/bin/sh
tar c -f - -C /svn/chroot \
  etc/ld.so.cache \
  lib/ld-2.3.6.so \
  lib/ld-linux-ia64.so.2 \
  lib/tls/libc.so.6.1 \
  lib/tls/libc-2.3.6.so \
  lib/tls/libcrypt.so.1 \
  lib/tls/libcrypt-2.3.6.so \
  lib/tls/libdl.so.2 \
  lib/tls/libdl-2.3.6.so \
  lib/tls/libm.so.6.1 \
  lib/tls/libm-2.3.6.so \
  lib/tls/libnsl.so.1 \
  lib/tls/libnsl-2.3.6.so \
  lib/tls/libpthread.so.0 \
  lib/tls/libpthread-2.3.6.so \
  lib/tls/librt.so.1 \
  lib/tls/librt-2.3.6.so \
  usr/bin/svnserve \
  usr/lib/libapr-0.so.0 \
  usr/lib/libapr-0.so.0.9.7 \
  usr/lib/libaprutil-0.so.0 \
  usr/lib/libaprutil-0.so.0.9.7 \
  usr/lib/libdb-4.3.so \
  usr/lib/libexpat.so.1 \
  usr/lib/libexpat.so.1.0.0 \
  usr/lib/libsvn_delta-1.so.0 \
  usr/lib/libsvn_delta-1.so.0.0.0 \
  usr/lib/libsvn_fs-1.so.0 \
  usr/lib/libsvn_fs-1.so.0.0.0 \
  usr/lib/libsvn_fs_base-1.so.0 \
  usr/lib/libsvn_fs_base-1.so.0.0.0 \
  usr/lib/libsvn_fs_fs-1.so.0 \
  usr/lib/libsvn_fs_fs-1.so.0.0.0 \
  usr/lib/libsvn_ra_svn-1.so.0 \
  usr/lib/libsvn_ra_svn-1.so.0.0.0 \
  usr/lib/libsvn_repos-1.so.0 \
  usr/lib/libsvn_repos-1.so.0.0.0 \
  usr/lib/libsvn_subr-1.so.0 \
  usr/lib/libsvn_subr-1.so.0.0.0 \
| \
tar x -vpf - -C /svn/chroot/chroot-repo --unlink-first
End

作った copy-files を実行してファイルをコピーする。

# ./copy-files

サーバ用のテンポラリディレクトリを作る。

# mkdir /svn/chroot/chroot-repo/tmp
# chmod 1777 /svn/chroot/chroot-repo/tmp

anonymous svn サーバを (外側の sarge 環境で動いている) inetd 経由で起動する設定をおこなう。

# echo 'svn stream tcp nowait root /usr/sbin/tcpd /usr/bin/chrootuid /svn/chroot/chroot-repo svnreader /usr/bin/svnserve -r /repo -i' >> /etc/inetd.conf
# /etc/init.d/inetd restart

コミッタが ssh 経由で接続したときのログインシェルを作る。これは個々のリポジトリにかかわらず共通なのでこのひとつでよい。ここで、このログインシェル自体は外側の sarge 環境で動くため、サーバ用の環境へ chroot しなければならない。しかし、このログインシェルはリポジトリ毎に割り当てた uid で動作するため、chroot するためには root 権限を得なければならない。そのために sudo を使うが、sudo の設定については、リポジトリの作成の設定の所で述べる。

# cat <<'End' > /svn/login
#!/bin/sh
# usage: /svn/login -c 'repo-name committer-name'
set -f # disable pathname expansion
set -- $2
exec /usr/bin/sudo /usr/bin/chrootuid /svn/chroot/chroot-repo "svn-$1" /usr/bin/svnserve -r /repo -t --tunnel-user "$2"
End
# chmod 755 /svn/login
#3 [svn] リポジトリを作る [CODE blog]

まず、なにはともあれ umask をちゃんとする。

# umask 022

リポジトリの名前をシェル変数に設定する。ここでは仮に foo という名前のリポジトリとするが、以下ではこの変数を使い、foo という名前は直接は参照しないこととする。

# REPNAME=foo

まず、そのリポジトリに uid を割り当てるためにユーザを作る。ホームディレクトリは root の持ち物としてその uid には変更させないので、事前に mkdir で作っておき、adduser ではホームディレクトリの生成を抑制する。また、ログインシェルとして先ほど作った /svn/login を指定している。

# mkdir /svn/home/svn-$REPNAME
# adduser --no-create-home --home /svn/home/svn-$REPNAME --shell /svn/login --disabled-password --gecos "svn $REPNAME" svn-$REPNAME

ホームディレクトリに .ssh ディレクトリを作る。これも root の持ち物とするが、そのユーザで読み込むことはできないといけないので、 owner を root, group をそのユーザ (に対応するグループ) とし、750 とする。

# (cd /svn/home/svn-$REPNAME; umask 027; mkdir .ssh; chown root:svn-$REPNAME .ssh)

etch 環境に chroot してその uid となり、subversion リポジトリを /tmp に作る。

# chrootuid /svn/chroot svn-$REPNAME /usr/bin/svnadmin create /tmp/repo-$REPNAME

作ったリポジトリをサーバ専用 chroot 内に移動する。

# mv /svn/chroot/tmp/repo-$REPNAME /svn/chroot/chroot-repo/repo/$REPNAME

ログインシェルで sudo できるよう、以下の設定を (外側の sarge の) sudoers に追加する。ここで、sudo で許すのはなるべく限定し、/usr/bin/chrootuid ... というコマンドラインに限定する。

# echo "svn-$REPNAME ALL = NOPASSWD: /usr/bin/chrootuid /svn/chroot/chrootrepo svn-$REPNAME /usr/bin/svnserve -r /repo -t --tunnel-user *" >> /etc/sudoers
#4 [svn] コミッタの登録 [CODE blog]

リポジトリ $REPNAME にコミッタを登録するには、コミッタ名とそのコミッタの ssh 用の公開鍵が必要である。

コミッタの名前をシェル変数に設定する。ここでは仮に bar という名前のコミッタとする。

# SVNUSER=bar

そのリポジトリに割り当てたユーザのホームディレクトリにある .ssh/authorized_keys にそのコミッタの公開鍵を設定する。ここで、no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty としてさまざまな ssh の機能を抑止し、さらに、command="$REPNAME $SVNUSER" としてこの公開鍵でログインしたときに行えるコマンドを限定する。このコマンドはログインシェルに渡され、ログインシェルは先ほど設定した /svn/login なので、 /svn/login -c "$REPNAME $SVNUSER" というように動作する。

# echo "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command=\"$REPNAME $SVNUSER\" TYPE1 KEY1 USER@DOMAIN" >> /svn/home/svn-$REPNAME/.ssh/authorized_keys
#5 [svn] chroot 環境の upgrade [CODE blog]

まず、etch 環境を upgrade する。

% sudo chroot /svn/chroot /bin/sh
(chroot-src)# apt-get update
(chroot-src)# apt-get --download-only upgrade
(chroot-src)# apt-get upgrade
(chroot-src)# exit

そして、サーバ専用 chroot へ、ファイルをコピーする。

% cd /svn
% sudo ./copy-files

2006-10-21 (Sat)

#1

ノートの HDD がクラッシュ

前回クラッシュして新しいのを買ってから半年くらいしかたってない。1.8inch って壊れやすい?

しかし、選択肢はないしなぁ。(いや、容量の小さいのを選ぶという選択肢はあるか?)

2006-10-23 (Mon)

#1 [cookie] cookie 仕様 [CODE blog]

最近、wfo (旧仮称 wvs) を作っていて、 cookie の (ブラウザ側の) 処理を実装するはめになったのでいくらか調べた。

まず、仕様が 3 つある。

それぞれに違うのであるが、とくに RFC 2965 は Cookie2, Set-Cookie2 という新しいヘッダを導入していてかなり違う。

また RFC 2965 は、 cookie を受け付けるかどうかを人間が判断するという話とか、プライバシ問題を念頭において作られた感がある。

しかし、出ている例は最初の Netscape のから変わらず、商品名とかを直接 cookie にするもので、最近の乱数を使うという常識に反する。クライアント側での改竄は考えてないのか?

ただ、クライアント側から cookie の domain を伝える機能があるのは RFC 2965 の利点である。これがあれば、cookie monster にも対抗できると思うのだが、実装状況がなぁ。

2006-10-25 (Wed)

#1

ラックの電源のアレ (コンセントプラグ)

摂津金属工業 DH2684 <URL:http://www.settsu.co.jp/japanese/pdf/n_dh.pdf>

愛三でも買える <URL:http://www.aisan.co.jp/products/oa_tap1.html>

#2 127.1 = 127.0.1 = 127.0.0.1 [CODE blog]

ふと、w3m や mozilla で、http://127.1/ や http://127.0.1/ が使えることに気がつく。

inet_aton(3) を読んでみると... お、さらに、http://0x7f.0.0.1/ や http://0177.0.0.1/ も使えるな。

うぅむ。http://0x7f.0x1/ なんていわれると、IP アドレスかどうかを文字列のパターンマッチで調べるのは厄介だな。

サーバが URL を受けとって、そこにアクセスする、といったサービス (翻訳とか、HTML の validation とか) に、こういう URL を与えると、内部のネットワークにアクセスしてしまったりすることもありうるという気もする。

まぁ、与えられた文字列のままじゃなくて、内部的な IP アドレスに変換してから検査していれば問題ないが。

というか、そうしないと、内部のネットワークを指すような A レコードを持つ名前を与えられたときにまずいから、必然的にそうしないといけないか。

しかし、そうすると気になるのは round robin な DNS だよなぁ。

2006-10-27 (Fri)

#1

ひさしぶりに gcc (の trunk) をコンパイルしてみると、GMP 4.1+ と MPFR 2.2+ 必要とのこと。

うぅむ。Debian には入ってないバージョンか。

とすると、chkbuild の中で作るのがいいと思うわけだが、バージョンによって依存先が変化するというのはいままだ扱った覚えがないな。

#2 [codeblog] textarea のサイズ [CODE blog]

稲田さんにいわれて、textarea のサイズを変えてみる。

まず、調べてみると、tDiary の編集用の textarea のサイズはテーマ別の CSS で定義されていることがわかった。

たとえば、default テーマでは以下のようになっている。

tdiary-2.0.2+20050720/theme/default/default.css:416-422

416: /*
417: (failed to encode)
418: div.section pre {
419:         background-color: #eef;
420:         color: #000;
421:         margin-left: 5em;
422:         margin-right: 1em;

この、width と height を変えれば変わるわけであるが、テーマはたくさんあるのでそのすべて変えるのはやりたくない。

そこで、もうすこし調べて、それを呼び出す HTML 側をいじることにした。

CSS を参照する link 要素は 00default.rb というデフォルトで読み込まれるプラグインの、css_tag というメソッドで生成されている。

tdiary-2.0.2+20050720/plugin/00default.rb:242-255

242: def css_tag
243:         if @conf.theme and @conf.theme.length > 0 then
244:                 css = "#{theme_url}/#{@conf.theme}/#{@conf.theme}.css"
245:                 title = css
246:         else
247:                 css = @css
248:         end
249:         title = CGI::escapeHTML( File::basename( css, '.css' ) )
250:         <<-CSS
251: <meta http-equiv="content-style-type" content="text/css">
252:         <link rel="stylesheet" href="#{theme_url}/base.css" type="text/css" media="all">
253:         <link rel="stylesheet" href="#{css}" title="#{title}" type="text/css" media="all">
254:         CSS
255: end

なので、これをいじる、というのもひとつの方法であるが、今回は 90codeblog.rb という新しいプラグインを作り、そこで css_tag を再定義することにしてみた。

90codeblog.rb の内容は以下の通りである。

alias codeblog_old_css_tag css_tag

def css_tag

result = codeblog_old_css_tag
result + <<'End'
      <style>

form.update textarea {

width: 90%;
height: 450px;

}

</style>

End

これは自動的に読み込まれるので、全員 textarea が大きくなったのではないかと思う。

#3 [codeblog] タイトルのリスト [CODE blog]

あと、昨日聞いた、全てのタイトルのリストを出したい、というのを調べてみる。

カテゴリプラグインをつかえばできるのだが、過去のエントリにカテゴリをつけないといけないのが大変だという話である。

調べてみると、そういうプラグインはない気がする。うぅむ。

ただ、もしセキュアモードでなければ、recent_list が使えなくもない気はする。 recent_list(10000000000000000000000000000000000000) とか。まぁ、codeblog はセキュアモードなので使えないが。

今回は以下のように調べた。

1. まず、カテゴリプラグインで可能、という話なので、それを試してみる
2. 機能から考えると、日記のデータにアクセスする部分があるはずなので、カテゴリプラグイン内でそれを探す: TDiaryMonth というクラスがそれらしい。そういえばデータは月ごとのファイルになっているのでたしかにそれっぽい
3. TDiaryMonth をプラグインディレクトリで grep する: category, navi_user, recent_list で見付かる。
4. navi_user を調べるが、セキュアモードでは使えず、また、期待される機能を実現するものではない
5. recent_list を調べると、セキュアモードでは使えないが、それっぽい機能がある。
6. 手元のノートに入っている tDiary をセキュアモードでなくして、recent_list を使ってみる: たしかに出るが、ヘッダやフッタに入れるのが想定されていて、独立したページにする機能はないっぽい

2006-10-28 (Sat)

#1

うぅむ。gmp の cvs リポジトリはは非公開なのか。

mpfr は svn リポジトリが公開されているようだ。

#2

現在の locale の文字コードを得るには ruby-locale を使うか、

% ruby -rdl/import -e '
module LIBC
  extend defined?(DL::Importer) ? DL::Importer : DL::Importable
  dlload "libc.so.6"
  extern "const char *setlocale(int, const char*)"
  extern "const char *nl_langinfo(int)"
  LC_ALL = 6
  CODESET = 14
end
LIBC.setlocale(LIBC::LC_ALL, "")
p LIBC.nl_langinfo(LIBC::CODESET).to_s
'
"EUC-JP"

などと、環境依存なコードにしないといけないかなぁ、と思っていたのだが、調べてみると、locale という (POSIX な) コマンドがあって、それで得られることがわかる。

debian% locale charmap
EUC-JP

netbsd% locale charmap
eucJP

2006-10-29 (Sun)

#1 [cookie] Cookie Monster [CODE blog]

へー、Cookie Monster で大量のクッキーをつけると、 Bad Request でアクセス不能にしてしまえるのか。

http://www.ornithopter.jp/archives/2006/06/cojp.html

2006-10-31 (Tue)

#1

お、PowerPC での話に返事が来た。 <URL:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28197>

gcc の問題じゃない、か。まぁ、順当な見解かな。

たしかに、setjmp が linkage area を記録して、longjmp が復旧すればいいはずだから。


[latest]


田中哲