クライアント

telnet -u が便利…だと思ったら MacOSXFreeBSD には telnet -u あるんだけど、手元の Linux には無いみたいで困る。 unixclient では作れないかなぁ…と思ったので Ruby でサックリと。

 require 'socket'
 
 sock = UNIXSocket.open(ARGV[0])
 
 inputs = [STDIN, sock]
 
 while true
   i, o, e = IO.select(inputs)
   i.each do |input|
     if input == STDIN
       c = STDIN.getc
       if c
         sock.putc(c)
         sock.flush
       else
         sock.close_write
         inputs = [sock]
       end
     elsif input == sock
       c = sock.getc
       if c
         STDOUT.putc(c)
       else
         exit
       end
     end
   end
 end

ucspi-unix には unixcat ってのがついていて、それで良さげに思えるんだけど、中身見ると

 exec unixclient "$1" sh -c 'exec cat <&6'

とかいう shell script (unixclient は unixserver のクライアントバージョンで、指定したプログラムと fd 6 と 7 を使ってやりとりする) で、これは unix domain socket の吐いた内容の出力はできるけど入力はできないと思う。入力をやるなら、

 cat >&7
 cat <&6

とかを実行させればいい気がするんだけど、なんにせよこれらだと接続終了時に終了しない。これはたぶんサーバ側の cat が終わってないからで、一個目の cat が終了した後に終わらない理由は書き込み側の終了を伝えてないからだと思う。 7 を閉じちゃえばいいようにも思えるんだけど、これ socket だから 6 も 7 も同じファイルディスクリプタで書き込み側とかの区別がなくて、閉じちゃえば接続が切れてしまって今度は受信ができない。 shell から shutdown(fd, SHUT_WR); 的なことができるといいんだけど。

このへんの事情は TCP socket も同じで、よくわからんけど、読み書きを一つのファイルディスクリプタでやるっていう設計のせいなのかなぁ。 TODO: Plan9 とかどうやってるんだろう。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h