9front (2)

若者が手に取って眺めていたので、オイラーも釣られて手に取ってみた。 はじめてのアプリガイド『今さら聞けないインスタグラム入門』 絵解きシリーズですなあ。最近の教科書風。

営業言葉で、インスタグラムは写真中心のSNSのため、素直に写真に共感出来ます。テキスト中心のSNSのように、炎上したり、誤解を招いたりの心配もありません。フェイスブックやツイターやラインはもう衰退ぎみというか、疲れちゃって使わなくなる人が多いそうとか。

オイラーがインスタグラムを知ったのは、イッテQでイモトが、インスタグラム、インスタグラムと騒いでいたから。ツイターとフェイスブックを足して2で割るとインスタグラムになるんか。

ぶすな人も写真写りが良くなるように加工をほどこせますって、こりゃもうみんな飛びつくわな。加工用のフィルターが23種も有るって、どんだけーーー!

これもそれも、いいねを貰いたいため。ファミレスで全メニューを注文して、それを写メして、 いいねを貰おうとした馬鹿とか、わー綺麗で、写真撮りまくりで、なんのために旅行に行ったんだやら。

オイラーは、写真大嫌い派。しっかり脳裏に刻んでおけばそれでいいじゃん。おかげで、近影の ものは一切無し。

それじゃ、もしもの時に困る人が出て来るだろう。ご遺影を事前に撮影しておくか。縁起でもない? 生前に自分の入る墓を作ると長生き出来るそうだから、それにあやかれないかな?

写したものは、後で加工出来るように、色々なフォーマットで保存しておけばいいのかな? それに、念を入れて、終活ノートにでも写真を挟んでおけばいいか。

介護保険の説明を受けに行った時、手回しよく終活ノートを配ってたんで、貰ったものが有るからね。

ftp

前回からの続きで、9frontと戯れる。9frontとのセッションの記録を曲がりなりにもFreeBSD側からtelnetする事で取れるようにした。そして、plan9側のeditorも、まあ使えるようになった。

でも、samだとかacmeでC語のファイルを開いた時に、ソースに色が付かないのは大いに不満。 Linuxと違って、最初からソースが付いてくるんで、これをサーフィンしなきゃ、つまらない。

そんなの簡単、ソースをFreeBSD側にごっそり持ってきちゃえばいいんでないかい。vim(オイラーは使わんけど)なりemacsで、色付きソースを見られるよ。

はて、どうやって持って来る? 9front.orgのサイトにfaqが公開されてて、そこに 8.4.4 - FTP の説明と言うか、ftpfsを見ろって言うリンクが有りましたよ。(faqをまとめたものが、releaseのリンクの先に、dash 1 manualとして公開されてる)

で、ftpfsの説明を斜め読みすると、外部に建っているftpサーバーに接続して、そのtop-dirを 9frontにマウントしちゃうと言う、荒技を繰り出すようだ。昔使った事があるNFSみたいなものね。但し、サーバーとのやり取りは、ftpプロトコルになるけどね。

ぐちゃぐちゃ書いても、読者は飽きてしまうだろうから、実行例を載せます。

ftpサーバーは、FreeBSD側にpythonのライブラリィーを使って建てます。そのサーバー目掛けて、9front側(クライアント)が、匿名で接続するって例。

[fb11: tmp]$ mkdir top; cd top
[fb11: top]$ echo This is FreeBSD >README
[fb11: top]$ sudo python2 -m pyftpdlib -i xxx.xxx.xxx.xxx -p 21 -w
/usr/local/lib/python2.7/site-packages/pyftpdlib/authorizers.py:243: RuntimeWarning: write permissions assigned to anonymous user.
  RuntimeWarning)
[I 2017-11-30 15:55:45] >>> starting FTP server on xxx.xxx.xxx.xxx:21, pid=797 <<<
[I 2017-11-30 15:55:45] concurrency model: async
[I 2017-11-30 15:55:45] masquerade (NAT) address: None
[I 2017-11-30 15:55:45] passive ports: None
[I 2017-11-30 15:56:21] xxx.xxx.xxx.1:53800-[] FTP session opened (connect)
[I 2017-11-30 15:56:21] xxx.xxx.xxx.1:53800-[anonymous] USER 'anonymous' logged in.
[I 2017-11-30 15:56:45] xxx.xxx.xxx.1:53800-[anonymous] CWD /tmp/top/README 550 'Not a directory.'
[I 2017-11-30 15:56:45] xxx.xxx.xxx.1:53800-[anonymous] RETR /tmp/top/README completed=1 bytes=16 seconds=0.001
[I 2017-11-30 15:57:42] xxx.xxx.xxx.1:53800-[anonymous] STOR /tmp/top/ed.c completed=1 bytes=22102 seconds=0.003
[I 2017-11-30 15:58:10] xxx.xxx.xxx.1:53800-[anonymous] FTP session closed (disconnect).

適当なdir内にREADMEと言う、FreeBSD側の証拠ファイルを用意。続いてサーバーを立てる。 21番の特権ポートが必要なのでroot権限。そして、誰でも書き込めるように(危険ですな)-wオプションを付与。後は、ログを眺めていれば宜しい。

尚、xxx.xxx.xxx.xxxはFreeBSDのIPアドレス。xxx.xxx.xxx.1は、デフォルトGWのアドレスです。

term% ftpfs -a hoge xxx.xxx.xxx.xxx
220 pyftpdlib 1.5.2 ready.
331 Username ok, send password.
230 Login successful.
215 UNIX Type: L8
257 "/" is the current directory.
term% cat /n/ftp/README
This is FreeBSD
term% cp /sys/src/cmd/ed.c /n/ftp
term% unmount /n/ftp

こちらは、vbox内にある9frontでの記録。FreeBSDへのルーチングは、Windows10に用意された仮想ネットワークがよしなにやってくれる。-aのオプションは、ftp接続する時のパスワード。 匿名ユーザーなんで、普通はメアドを入れるのが礼儀。実際は難でもいいんでhogeとした。

この-aを省くと、気を利かせてグレンダちゃんで接続しようとして、面倒な事になる。

次は、サーバー側に用意したREADMEが読めるか確認。ftpfsのマウントポイントは、-mオプションで適当な所に設定出来る。この指定をしないと、デフォで/n/ftpが使われる。 続いて、ed.cをコピーした。これがftpで言うupload相当になる。ftpの切断は、unmountで、マウントの解除がトリガーになる。

[fb11: top]$ ls -l
total 28
-rw-r--r--  1 sakae  wheel     16 Nov 30 15:52 README
-rw-r--r--  1 root   wheel  22102 Nov 30 15:57 ed.c

そして、FreeBSDに残された結果。確かにed.cがやってきてる。但し、rootの持ち物としてね。

このrootで起動ってのは、大きな足枷になるな。危険でもあるし。それもこれも21番の特権ポートはrootでしか操作出来ないからだ。 (尚、9frontには、特権ポートと言う概念は無いそうだ。)

一般ユーザーで、python製可搬型サーバーを立てると

starting FTP server on xxx.xxx.xxx.xxx:2121

ってなるんで、これに合わせて、9front側を調整したいぞ。

acid

ちょっとplan9portの時のリベンジでacidと言うdebuggerが動くかやってみる。 こやつは入出力にstderrとかも使っているようで、それを含めてログしようと

term% acid -l truss /bin/ls |& tee LOG

とかやったら、rcはbashとかと違って、アンパサントの解釈が出来ないみたい。 しょうがないので、グラフィック端末で実行して、そのセッション結果をedにコピペ した。

term% acid -l truss /bin/ls
/bin/ls:386 plan 9 executable
/sys/lib/acid/port
/sys/lib/acid/386
/sys/lib/acid/truss
acid: new()
acid: truss()
brk_(0x00011b30)
        return value: 0
stat(".", 0x00010b74, 115)
        return value: 73
open(".", 0)
        return value: 3
brk_(0x00021bd8)
        return value: 0
pread(3, 0x00010b38, 65595, 4294967295)
        return value: 210
        data: 0x00010b38, 210
pread(3, 0x00010c0a, 65595, 4294967295)
        return value: 0
        data: ""
brk_(0x00022c00)
        return value: 0
close(3)
        return value: 0
pwrite(1, "bin
lib
tmp
", 12, 4294967295)
bin
lib
tmp
        return value: 12
571: breakpoint _exits+0x5      INTB    $0x40

上記はマニュアルに載ってた例。ちゃんとtruss出来た。ああ、リナにしか知らない人がいると 可哀そうなので、straceですって教えてあげるよ。

所で、preadの数字の並びは何よ。そんな時はシグネチャを確認すると良い。まあ、これって haskellで言う、型宣言だな。

term% sig pread
        long pread(int fd, void *buf, long nbytes, vlong offset)

acid実行の冒頭付近に/sys/lib/acid/が出てきてる。興味をもってそこを覗いてみると、 syscallなんてのを発見。acidで使うデータだな。面白いので一部を載せておく。

syscalls = {
        { 0, {"sysr1",          "s",            code(0)}},
        { 1, {"_errstr",        "s",            code(*sys_errstr:list)}},
        { 2, {"bind",           "ssX",          code(*sysbind:list)}},
        { 3, {"chdir",          "s",            code(*sysbind:list)}},
          :
        {50, {"pread",          "DADZ",         code(*syspread:list)}},
        {51, {"pwrite",         "DTDZ",         code(*syspwrite:list)}},
        {52, {"tsemacquire",    "AD",           code(*systsemacquire:list)}},
        {53, {"_nsec",          "A",            code(*sys_nsec:list)}},
};

えっ、システムコールがこれしか無いの?それとも、acidの都合で、良く出て来るものを 選りすぐってサービスしますって事?

term% cat truss
// poor emulation of SVR5 truss command - traces system calls

include("/sys/lib/acid/syscall");

ベル研生まれのplan9の末裔9frontもしっかりと内部にDNAを抱えこんでいるなあ。

ああ、acidのサービスでトランプ野郎も居るぞ。こやつの特技はツイターじゃなくて、

// trace user malloc pool - trace malloc, realloc, and free calls
// if trumpsbrk is set, we trace sbrkalloc and sbrkmerge too.

こういう事みたいだ。やっぱり追跡じゃん。

ftpfs改造

acidもちゃんと動いたので、ftpfsの改造に挑戦してみよう。改造ポイントは、21番ポートじゃなくて、pyftpdlibに合わせて、2121番ポートにする事。

term% cp /sys/src/cmd/ip/ftpfs/* .
term% ls
file.c
ftpfs.c
ftpfs.h
mkfile
proto.c
term% cat mkfile
</$objtype/mkfile

TARG=ftpfs
HFILES=ftpfs.h
OFILES=ftpfs.$O\
        proto.$O\
        file.$O\

BIN=/$objtype/bin

UPDATE=\
        mkfile\
        $HFILES\
        ${OFILES:%.$O=%.c}\

</sys/src/cmd/mkone

ソースの在処はmanに明記されていると言う厚遇。これはもう自由に閲覧せい、そしてhackせいと言う文化ですな。手元のtmpにコピーしてきた。mkfileがちゃんと用意されてた。 tmpの下で、コンパイル出来るか、そして新たに出来(るであろう)たバイナリーが動くか 確認。なんせ知らない所ですから、手探りで進みます。

term% mk
8c -FTVw ftpfs.c
8c -FTVw proto.c
8c -FTVw file.c
8l  -o 8.out ftpfs.8 proto.8 file.8

無事にコンパイルが完了して、8.outが出来上がった。こやつがきちんと動くかどうかを、tmpの下を全部FreeBSD側に転送。そして、FreeBSD側で、改造ポイントを心おきなく観察。(ソースの閲覧は、なんたってemacsが便利)

proto.cの中に、こんなのを発見。

/*
 *  connect to remote server, default network is "tcp/ip"
 */
void
hello(char *dest)
{
        char *p;
        char dir[Maxpath];

        Binit(&stdin, 0, OREAD);        /* init for later use */

        ctlfd = dial(netmkaddr(dest, "tcp", "ftp"), 0, dir, 0);
        if(ctlfd < 0){
                fprint(2, "can't dial %s: %r\n", dest);
                exits("dialing");
        }

netmkaddr関数の中で、必要なソケットを作っているんだな。ftpは、どこかにある 変換テーブルで数値に変換されるんだろう。丁度unixで持ってる/etc/servicesみたいな dbが有るに違いない。

[fb11: ~]$ less /etc/services
 :
ftp              21/tcp    #File Transfer [Control]
ftp              21/udp    #File Transfer [Control]
ssh              22/sctp   #Secure Shell Login
ssh              22/tcp    #Secure Shell Login
ssh              22/udp    #Secure Shell Login
telnet           23/tcp
telnet           23/udp

ならば、"ftp" ってなってる部分を先回りして、2121に変更しちゃえ。

term% mk
8c -FTVw proto.c
proto.c:81 argument prototype mismatch "INT" for "IND CHAR": netmkaddr
term% sig netmkaddr
        char* netmkaddr(char *addr, char *defnet, char *defservice)

なんとまあ、エラーになったぞ。数値で指定はダメっぽい。型宣言を確認する。って、haskellで、ごちゃごちゃやってるみたいだな。文字列を強要されてるんで、しかたなくそうしてみる。 (内心は、プチ不本意ではありますが。おじいちゃん言いつけでは、マジックナンバーは使うなと)

term% ed proto.c
30341
/2121/
        ctlfd = dial(netmkaddr(dest, "tcp", 2121), 0, dir, 0);
s/2121/"2121"/
p
        ctlfd = dial(netmkaddr(dest, "tcp", "2121"), 0, dir, 0);
w
30343
q
term% mk
8c -FTVw proto.c
8l  -o 8.out ftpfs.8 proto.8 file.8

今度はコンパイル成功。出来上がった8.outをbin/ftpfsって名前で置いて、動作確認。 ちゃんと動いた。これにて一件落着。それにしても、変換テーブル何処に置いてあるのだろう?

network

Windows7のVMWareに入れた9frontなんだけど、dhcpでアドレスを取っているものだから、 どんなIP-Addressが取れたか知れない。ifconfigなんてコマンドは無いし、似たようなコマンドでipconfigが有るけど、こやつは設定だけ。

思い余って、よそのFreeBSDからpingで総舐めしてやろうかと思った。あるいはnmapとかね。 でも、それって不良の始まりじゃなかろうか? 通報されたら、申し開きが面倒そう。場合に よっては、危ない人の烙印を押されて、監視対象にされかねない。

そんな事なんで、9frontに閉じだ形で、調べてみる事にした。ndbに問い合わせすれば宜しい って事が判明。cirnoってのは、host名だ。インストール時に、サルのごとくRETを叩いて いると、デフォのcirnoって名前(アニメの女の子の名前だそうだ)になる。今から思えば、 オイラーはそんな趣味はないぞ。

term% ndb/query sys cirno
ip=10.0.2.15
ipmask=255.255.255.0
ipgw=10.0.2.2
sys=cirno
dom=cirno.hoge.fuga.jp
dns=yyy.yyy.yyy.1
sys=cirno
ether=0800abcdef10

見易いように改行を適当に入れ、かつちょっと匿名化してある。まあ、普通に分かるよね。

term% netaudit
checking this host's tuple:
        ip=10.0.2.15 looks ok
        dom=cirno.hoge.fuga.jp looks ok
        ether=0800abcdef10 looks ok
checking the network tuple:
        we are not in an ipnet, so looking for entries in host tuple only
        ipgw=10.0.2.2 looks ok
        dns=yyy.yyy.yyy.1 looks ok
        no auth= entry
        no fs= entry (needed for tls boot)
checking auth server configuration:
        no auth server

そして、こちらは、9front本来の構成を取った時の情報。なんたって、ネットワークを経由 して、認証サーバーとかが存在してますからねぇ。

term% ls -l /lib/ndb
--rw-rw-r-- M 26 sys sys   610 Jan 18  2012 /lib/ndb/auth
--rw-rw-r-- M 26 sys sys 10139 May  2  2017 /lib/ndb/common
--rw-rw-r-- M 26 sys sys    95 Jan 18  2012 /lib/ndb/consoledb
--rw-rw-r-- M 26 sys sys    61 Jan 18  2012 /lib/ndb/dnsdump
--rw-rw-r-- M 26 sys sys   962 Nov 20 13:41 /lib/ndb/local
--rw-rw-r-- M 26 sys sys  2975 Sep 11 05:35 /lib/ndb/local.complicated
--rw-rw-r-- M 26 sys sys   113 Jan 18  2012 /lib/ndb/nfs

これらが、設定の元情報。どこかのOSみたいにbinaryじゃなくてAsciiファイルになってるのは 良い事と思うぞ。

で、Windows7で確認したら、IPアドレスが判明。導通試験としてping。それから、ncコマンドを使って接続。ncはtelnetと違って、行末に余計なCRを挿入しないので、9front側で、trを省略出来る。なんと、一行野郎で、セッションを貼れるって素敵。

find

9frontのextraにfind.cなんてのが置いてあったので入れてみた。

term% hget http://9front.org/extra/find.c >find.c

取り寄せはcurlもどきのhgetを使うと便利。find.cが手元に来たら、8cと 8lを実行してコンパイル。出来上がった8.outを自dirのbinの下にfindとして登録。マニュアルも公開されてるので 取ってきた。find.1との事なので、/sys/man/1/findとして置いた。

man find

     FIND(1)                                                   FIND(1)

     NAME
          find - recursively list files.

     SYNOPSIS
          find [ -1Ddfq ] dir ...

     DESCRIPTION
          List each argument.  If the argument is a directory recur-
          sively list it's contents.  The default is to list the cur-
          rent directory.  Specifying -d prints only directories, -D
          prints only files, -f supresses warnings, while -q supresses
          quoting the output for rc(1). With -1, mount points will not
          be traversed.

     SOURCE
          /sys/src/cmd/find.c

     SEE ALSO
          du(1)

     BUGS
          Feeping creaturism.

ゲームのソースで複雑なやつ(はdirの中に有る)

term% bin/find -d /sys/src/games
/sys/src/games
/sys/src/games/blabs
/sys/src/games/blit
/sys/src/games/c64
/sys/src/games/doom
 :

実行スクリプトファイルを抽出する。

term% bin/find -D /bin | xargs file | grep -v 386
/bin/ape/psh:   rc executable file
  :
/bin/wloc:     rc executable file
/bin/wurl2txt: rc executable file
/bin/xls2txt:  rc executable file
/bin/riostart: rc executable file

rc

ここら辺で、rcスクリプトのmanじゃなくて、実例を見ておく。簡単そうなやつ。

term% cat /bin/wloc
#!/bin/rc

rfork e
ifs='
'

for(i in `{ls /dev/wsys}) {
        echo window -r `{syscall -o read 0 buf 59 < $i/window >[2] /dev/null |
        sed 's/............//; s/^ *//; s/  */ /g'} `{cat $i/label}
}

for文で回して、それぞれの情報を採取してるんだな。

term% ls /dev/wsys
/dev/wsys/1
/dev/wsys/2
/dev/wsys/3
term% ls /dev/wsys/1
/dev/wsys/1/cons
/dev/wsys/1/consctl
/dev/wsys/1/cursor
/dev/wsys/1/kbd
/dev/wsys/1/label
/dev/wsys/1/mouse
/dev/wsys/1/screen
/dev/wsys/1/snarf
/dev/wsys/1/text
/dev/wsys/1/wctl
/dev/wsys/1/wdir
/dev/wsys/1/window
/dev/wsys/1/winid
/dev/wsys/1/winname
/dev/wsys/1/wsys

forが出てきたけど、微妙に文法が違うなあ。こういうのは、出来ればパイプで書いてしまいたい。何たって、パイプの連結で処理するのって、関数的な考え方ですからね。

goby

そんな事を言うと、rubyでメソッドチェーンはどうよと言われそう。

今やC語は古いでしょ。これからはgoでしょって事で、goで作ったrubyがあるそうな。 台湾の方がやっておられる。まだ、Linuxでしか動かないそうなんで、 goby-lang/goby とか Goby: Rubyライクな言語(1)Gobyを動かしてみる を参考に、debianに入れてみた。

debian:~$ cd go/src/github.com/goby-lang/goby/
debian:goby$ ls
bzt.yml             Dockerfile  Makefile                    travis.sh
codecov.yml         goby.go     prepare_travis_for_fork.sh  vendor
CODE_OF_CONDUCT.md  Godeps      README.md                   vm
compiler            igb         samples                     wiki
_config.yml         lib         snap
CONTRIBUTING.md     LICENSE     test_fixtures
debian:goby$ export GOBY_ROOT=`pwd`
debian:~$ ~/go/bin/goby -i
Goby 0.1.3 
» 123 + 456
#» 579

にこちゃんマークが出て来るらしいけど、化けてしまった。emacsにセッションログをコピペしたら、異物な文字コードに感化されて激遅い 状態になったので、マークだけを削除。

ダメ元で、OpenBSDでも実行。golangはパッケージになってたので、サクッと入れた。

$ go version
go version go1.9 openbsd/amd64
$ /home/sakae/godev/bin/goby -i
Goby 0.1.3
» p "hello goby"
#» UndefinedMethodError: Undefined Method 'p' for <Instance of: Object>

まだ先は長いね。グァンバッて下さい。台湾国際チームご一同様。一応OpenBSDでも動いた事を 謹んでご報告申し上げます。

こういうのは、トランプ野郎みたいにつぶやくのがいいんだろうね。オイラーは、ツイターも フェースブックもインスタグラムも、強迫観念に落ち込みそうなので、一切やってないからね。 ひっそりと、昔風のWebに載せるだけさ。奇特な方がおられたら、拡散希望。