9front (4)

朝雪が降っていたけど止んで、陽が差してきたので散歩に出た。と、車と人通りが少ない新興住宅地にさしかかった所、道路の真ん中でおじいさんが尻もちをついていた。

手招きされた。どうしたんです?(そんなの見れば分かるじゃん。我ながら情けない問い。) ろれつが回らない風。朝っぱらから飲んだくれ? でもない。

ころんで起き上がれなくてSOSが発信されてるんだよ。近づいてみると、杖をお持ち。自助努力で立ち上がろうとするが、足腰が弱っていてだめ。

手を出してきたんで、その手をつかんで立たせてあげようとするも、ガタイが大きくてオイラーには無理。更に両手を掴んで立たせようとするも、途中までたって、元も木阿弥。

後ろに回って、背中から抱きかかえて、重い荷物を持ち上げる要領でやったら、何とか立たせて あげられた。第三の足、杖も使えて、やっと3点支持で自立できたぞ。

おっかなびっくりに支えていた手を放すと、一歩二歩と亀の歩みで動き出した。オイラーよりも 背丈は高いし、防寒具のダブダブを除いても断然に恰幅が良い。

あいさつは言葉にならず、頭を下げるだけ。きっと脳卒中か何かに不自由になったのでしょう。 オイラーのn年後を見てるような気がして思わず、『情けは人の為ならず』を思い出したぞ。

その時は気が動転してたけど、後で思い出すと、首から下げていた携帯は通話を試みたように、 蓋が開いた状態になってた。多分、助けを呼ぼうとしたけど手袋が障害になって電話出来なかったんだろうな? それとも、特殊な携帯でSOSを発信出来るようになっていたのかな?

あと、お洒落な帽子と派手な黄色の防寒着を召されていたな。きっと家族の思いやりがこもって いるんだろう。それから、ほのかに香水と言うかオーディコロンの匂いがしたように思う。 手を鼻に近づけたら、確かに良い香りがした。お洒落な人だったんだなあ。

nc of OpenBSD

前回、Plan9port(in OpenBSD)に入ってるdial(1)をちょっと触った。同様な機能の物がncである。OpenBSDにも勿論入っているので、gdbにかけて動きを追ってみたい。それには、ncの 再コンパイルが必要だな。/usr/src/usr.bin/ncに置いてあるMakefileにちょっと細工する。

CFLAGS= -g

そしてコンパイルすれば良い。その点、p9pや9frontのそれは何もしなくても、最初からacidに かかるようになってる。cmdだけじゃなくてlibもacidですいすいて潜っていける所が、Linuxには無い醍醐味である。

今回は、IPアドレスとかで指定するんじゃなくて、FQDNで指定してみて、どう動くか見る。 日頃沢山アクセスが有るであろうヤッホーをターゲットにする。あれあそこってググル様のご指導によりhttps化されてるよね。そのポート番号って確か443番だったはず。じゃヤッホーのIPは知ってるか? そういう場合にプロはdigとかを使うらしいけど、こちとらはアマチュアなんで、軽くお茶を濁しておく。

$ host www.yahoo.co.jp
www.yahoo.co.jp is an alias for edge.g.yimg.jp.
edge.g.yimg.jp has address 183.79.248.252
(gdb) r www.yahoo.co.jp https
Starting program: /usr/src/usr.bin/nc/nc www.yahoo.co.jp https

Breakpoint 1, main (argc=3, argv=0x7f7ffffe91f8) at netcat.c:152
152             int ch, s = -1, ret, socksv;

お決まりのmainで止めて、丹念に追って行くと、コマンドラインの入力を内部変数に取り込んでいた。

 381        } else if (argv[0] && argv[1]) {
 382=>              host = argv[0];
 383                uport = argv[1];

更に進めて行くと、portの名前を数字に置き換えるルーチンに出会った。

(gdb) bt
#0  strtoport (portstr=0x7f7ffffe936f "https", udp=0) at netcat.c:1380
#1  0x00001dc345b040e7 in build_ports (p=0x7f7ffffe936f "https") at netcat.c:14\29
#2  0x00001dc345b026ab in main (argc=2, argv=0x7f7ffffe9200) at netcat.c:636

で、その中身。

1378        if ((entry = getservbyname(portstr, proto)) == NULL)
1379                errx(1, "service \"%s\" unknown", portstr);
1380=>      return ntohs(entry->s_port);

それが済むと、コネクトの部分に行く。

 892remote_connect(const char *host, const char *port, struct addrinfo hints)
 893{
 894        struct addrinfo *res, *res0;
 895        int s = -1, error, on = 1, save_errno;
 896
 897=>      if ((error = getaddrinfo(host, port, &hints, &res0)))
 898                errx(1, "getaddrinfo for host \"%s\" port %s: %s", host,
 899                    port, gai_strerror(error));

getaddrinfoの第三引数にホスト名をIPaddressに変換(DNSを引く)格納するんだな。ちなみに、第一、第二の引数は次の通り。

(gdb) p port
$7 = 0x1dc5c748fb80 "443"
(gdb) p host
$8 = 0x7f7ffffe935f "www.yahoo.co.jp"

この後、タイムアウト付きでconnectされるようになってた。

dial of 9front

今度は9frontでやってみる。

open("/net/cs", 2)
        return value: 3
pwrite(3, "tcp!www.yahoo.co.jp!https", 25, 4294967295)
        return value: 25
seek(0x00007a0c, 3, 0, 0)
        return value: 0
pread(3, 0xdfffed8c, 127, 4294967295)
        return value: 32
        data: "/net/tcp/clone 182.22.31.252!443"
open("/net/tcp/clone", 2)
        return value: 4
pread(4, 0xdfffe9dc, 255, 4294967295)
        return value: 1
        data: "2"
pwrite(4, "connect 182.22.31.252!443", 25, 4294967295)
        return value: 25
open("/net/tcp/2/data", 2)
        return value: 5
close(4)
        return value: 0
close(3)
        return value: 0
526: breakpoint _exits+0x5      INTB    $0x40

どうやら、/net/csが、host名とport名の解決問い合わせだな。そして、そこから返ってきた データを使って接続するとな。unixのネットワーク関連は、ごちゃごちゃしてて捻くれていて 悪いインターフェースの見本だ。カリフォーニアの人が、あっけらかんと動けばいいじゃんと 言う態度で実装したに違いない。

それで、東海岸の人が綺麗に実装しなおしてみせたんだな。

下記はちょっとしたacidの使い方。

acid: bpset(filepc("dial:45"))
acid: cont()
511: breakpoint dial+0x4a       CMPL    0x114(SP),$0x0
acid: src(*PC)
/sys/src/libc/9sys/dial.c:45
 40             ds.local = local;
 41             ds.dir = dir;
 42             ds.cfdp = cfdp;
 43
 44             _dial_string_parse(dest, &ds);
>45             if(ds.netdir)
 46                     return csdial(&ds);
 47
 48             ds.netdir = "/net";
 49             rv = csdial(&ds);
 50             if(rv >= 0)
acid: mem(dial:ds, "7s")
tcp *!http tp (null) (null) (null) (null)

もうネット方面はこれぐらいにしておくかな。

python

何処にでも生息する蛇が9frontにも、御多分に漏れず居るそうなので。

term% python
Python 2.5.1 (r251:54863, Oct 30 2017, 03:58:19) [C] on plan9
Type "help", "copyright", "credits" or "license" for more information.
>>>

ちょっと古いけどね。で、へそ曲がりな事に、pythonとのセッションはunix側の端末には一切 流れてこないので、rioのGUI画面で結果をファイルにコピペした。表示方法はpython独自な やり方をしてるんだろうか? どんな方法? pythonの巣ごもりで、独自の環境を作って その中で表示するとか。だから、unix側に開いているパイプの一端にはやり取りが流れない。

なにかヒントが無いかと思って、過去のpythonとの戯れを思い出してみると、どんな風に コンパイルされたか等を白状するモジュールが有った事を思い出した。

term% python -m ./sysconfig.py
Traceback (most recent call last):
  File "/sys/lib/python/runpy.py", line 85, in run_module
    loader = get_loader(mod_name)
  File "/sys/lib/python/pkgutil.py", line 456, in get_loader
    return find_loader(fullname)
  File "/sys/lib/python/pkgutil.py", line 466, in find_loader
    for importer in iter_importers(fullname):
  File "/sys/lib/python/pkgutil.py", line 417, in iter_importers
    raise ImportError("Relative module names not supported")
ImportError: Relative module names not supported

見事にエラー。わざと出目を隠していないかい! どんなコードになってるか行番号を頼りに 覗いてみたいものだ。そんなの簡単 cat -n でしょ。ブブー、シンプルを旨とするplan9のcatには、そんなオプションは無い。 ソフトウェアの単純さとか、 忍び寄る機能主義は、興味深い記事。

そういう時は、edの登場です。

term% cd /sys/lib/python/distutils
term% ed sysconfig.py
19248
,n
1       """Provide access to Python's configuration information.  The specific
2       configuration variables available depend heavily on the platform and
3       configuration.  The values may be retrieved using
:
536         get_config_vars().get(name)
537         """
538         return get_config_vars().get(name)
Q
term%

目的ファイルを読み込み、カンマnを実行。カンマは、1,$の省略と見做されますんで、全行をn(行番号付きで)表示しなさい。最後にQコマンドで、ファイルに書き込む事無く終了。 馬鹿とはさみは使いようですね。

Ruby 1.8.xをPlan9で動かす、ってpythonだけじゃやだって方の労作です。

sys/doc

/sys/docの下に、いわゆるシステムの取り扱い説明書が置いてある。ご丁寧にps形式だったりms形式だったりhtml形式だったりだ。manの生原稿が有れば、形式の変換はお手の物。 unix開発の公式理由は、写植システムの開発ってのが有るんで、面目が保たれているんだ。

でも、それを隠れ蓑にして、 開発を快適に行うためにOSを整備したり、もろもろのツールを作ったり(開発に行き詰まった時に使う、息抜き用のゲームも必需品)したという、おおらかな時代。outputを厳密に求められない佳き環境(研究所)が有ったというから恵まれていたな。

で、どんなのが有るか見てみたい。使い道の余りなさそうな蛇に登場願おう。

term% cd /sys/doc
term% python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.0.2.2 - - [20/Dec/2017 14:36:21] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [20/Dec/2017 14:36:21] code 404, message File not found
10.0.2.2 - - [20/Dec/2017 14:36:21] "GET /favicon.ico HTTP/1.1" 404 -
10.0.2.2 - - [20/Dec/2017 14:38:08] "GET /net/net.html HTTP/1.1" 200 -
10.0.2.2 - - [20/Dec/2017 14:38:08] "GET /net/tree0.png HTTP/1.1" 200 -
10.0.2.2 - - [20/Dec/2017 14:38:08] "GET /net/net1.png HTTP/1.1" 200 -
10.0.2.2 - - [20/Dec/2017 14:39:17] "GET /9.html HTTP/1.1" 200 -

同じものがNet上にも有ったぞ。 Plan 9 — The Documents (Volume 2) と思ったら、中身が空じゃん。 The Organization of Networks in Plan 9こちらの方は中身が詰まっているな。

Implementation Plan 9 C Compilers に面白い記述が有ったぞ。

SPARC   kc  kl  ka
Power   PC  qc  ql
MIPS    vc  vl  va
Motorola    68000  1c  1l
Motorola    68020  2c  2l
ARM 7500  5c  5l
Intel   960  6c  6l
DEC Alpha  7c  7l
Intel   386  8c  8l
AMD 29000  9c  9l

これの類を何処かで見た事が有る。えーとね、えーとね。golangのソース上。但し、最近のgoは 自分自身で自分をコンパイル出来るようになってるので(セルフコンパイル)入っていないはず。

FreeBSDのportsを探ったら、最近の1.9.2用に並行して、go14が置いてあった。このgo14が 各アーキテクチャ用の最後の世代なんだな。これが有るとboot用のgoが作れて、それを使って 最新式のgoを構築出来るとな。go14を入れてみた。

[fb11: cmd]$ pwd
/usr/local/go14/src/cmd
[fb11: cmd]$ ls
5a/             6g/             addr2line/      gc/             objdump/
5c/             6l/             api/            go/             pack/
5g/             8a/             cc/             gofmt/          pprof/
5l/             8c/             cgo/            internal/       yacc/
6a/             8g/             dist/           ld/
6c/             8l/             fix/            nm/

ARM,Intel 960,Intel 386に対応してるとな。開発者が同じだと、名前の付け方も一緒か。 9frontに手を出すような好き者じゃなくても、8xぐらいは眺めておいた方が良いかも。

// Inferno utils/8l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
//
//      Copyright 1994-1999 Lucent Technologies Inc.  All rights reserved.
//      Portions Copyright 1995-1997 C H Forsyth (forsyth@terzarima.net)
//      Portions Copyright 1997-1999 Vita Nuova Limited
//      Portions Copyright 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//      Portions Copyright 2004,2006 Bruce Ellis
//      Portions Copyright 2005-2007 C H Forsyth (forsyth@terzarima.net)
//      Revisions Copyright 2000-2007 Lucent Technologies Inc. and others
//      Portions Copyright 2009 The Go Authors.  All rights reserved.

と、一部を覗いてみたぞ。 Lucent Technologies Inc ってなってるけど、その前身はATTの 誇るベル研。unix生誕の地。goにもunixの血が流れているのがこの広告ではっきりしたな。

先のplan9のマニュアルを(斜めに)見ていたら、ndbの説明が出てた。詳細はndb(6)に詳しいんだけど、発見が有った。

term% cd /lib/ndb
term% grep http *
common:tcp=http port=80
common:tcp=https port=443
common:tcp=vnc-http port=5800

commonって名前のファイルが、unixで言う /etc/sevicesの役目を担っているのね。親切に vnc用の奴まで載ってるよ。

と思ったら、real dns root server ips も掲載。 これって、unix界でもたまに更新されるファイルだったな。えと、何て言う名前だ? 思い出されないので OpenBSDで漁ってみたら、/usr/src/usr.sbin/bind/lib/dns/rootns.cにハードコートされてた。

static char root_ns[] =
";\n"
"; Internet Root Nameservers\n"
";\n"
"$TTL 518400\n"
".                       518400  IN      NS      A.ROOT-SERVERS.NET.\n"
 :
"A.ROOT-SERVERS.NET.     3600000 IN      A       198.41.0.4\n"
"A.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:503:BA3E::2:30\n"
 :
"M.ROOT-SERVERS.NET.     3600000 IN      A       202.12.27.33\n"
"M.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:DC3::35\n";

変化するDNSとサーバー証明書の関係~「ランチのおともにDNS」より最近のDNSって、超責任重大な事になってるのね。知らんかったわい。

ip protocol numbers には、ipのプロトコル番号が4とか、tcpは6とかudpは17とか、他の 知らないものが多数列挙されてた。/etc/protocols も兼ねているんか。 これで、胸のつかえが降りたよ。

Plan9のネットワークって面白いな。次の記事はその一例。 ネットワークはどう抽象化されるのか?

Plan 9 Network Database

build kernel

で、面白い機能はどう実現されてる?ネットワークアクセスと言っても、下支えしてるNICがあってこそ実現可能。となれば、カーネルの出番。いよいよカーネルをコンパイルしてみる。そこからカーネルの何かが分かるだろう。FAQの案内に則って、

term% pwd
/sys/src/9/pc
term% time mk >LOG
processing ../boot/bootfs.proto
file system made
4.07u 1.29s 6.75r        mk

pcってのは、i386なマシンの事ね。この他にpc64とかbcm(arm)とかも有る。 一応、コンパイル時間と、ログを残すようにしてみた。7秒でコンパイル完了とな。機能を 絞っているんで、コンパイル行数が少ないんだな。小粒なOpenBSDでもカーネルをコンパイルすると3分ぐらいはかかっていたはずだから、雲泥の差だ。

term% ls *.8 | wc
    211     211    2096

211個の部品を組み合わせて、9pcと言うカーネルが出来上がるとな。

--rwxrwxr-x M 26 glenda sys      97 Dec 21 16:20 reboot.out
--rw-rw-r-- M 26 glenda sys    3512 Dec 21 16:20 init.h
--rw-rw-r-- M 26 glenda sys   17769 Dec 21 16:20 pc.c
--rwxrwxr-x M 26 glenda sys     689 Dec 21 16:20 init.out
--rw-rw-r-- M 26 glenda sys     355 Dec 21 16:20 reboot.h
--rw-rw-r-- M 26 glenda sys 1723346 Dec 21 16:20 bootfs.paq
--rw-rw-r-- M 26 glenda sys     988 Dec 21 16:20 apbootstrap.h
--rw-rw-r-- M 26 glenda sys    2260 Dec 21 16:20 errstr.h
--rwxrwxr-x M 26 glenda sys     222 Dec 21 16:20 apbootstrap.out
--rwxrwxr-x M 26 glenda sys   50037 Dec 21 16:20 boot
--rw-rw-r-- M 26 glenda sys   28453 Dec 21 16:20 sd53c8xx.i
--rw-rw-r-- M 26 glenda sys 9191919 Dec 21 16:20 pc.root.s
--rw-rw-r-- M 26 glenda sys     703 Dec 21 16:20 pc.rootc.c
--rw-rw-r-- M 26 glenda sys    8705 Dec 21 16:20 LOG
--rwxrwxr-x M 26 glenda sys 4409685 Dec 21 16:20 9pc

namespace

9frontの大きな特徴としてnamespaceってのが有るそうな。オイラーにとっちゃ意味不なんで 取り合えず、man 4 namespace してみた。

user's profileが実行されると、何でもファイルに見立ててアクセスできるようになるとな。 unixみたいにネットワークを使う時、socketして種を作り、bindでIP Addressとportを紐付けてからconnectで接続するなんていう変な作法は無し。

で、manが言う事には、便利なファイルの口が多数紹介されてた。 丁度FreeBSDあたりのhier(7)の気分。面白そうなので、ちょいとその一部を挙げてみた。 これって、9front内を歩き回る時の便利な地図と思われるぞ。

          /386/mkfile   Selected by mk(1) when $objtype is 386, this
                        file configures mk to compile for the Intel
                        x86 architecture.
          /lib/ndb      The network database used by the networking
                        software; see ndb(6) and ndb(8).
          /lib/namespace
                        The file used by newns (see auth(2)) to estab-
                        lish the default name space; see namespace(6).
          /cfg/system   System-specific files, often addenda to their
                        namesakes, notably cpurc, termrc, namespace,
                        and consoledb.
          /net/cs       The communications point for the connection
                        server, ndb/cs (see ndb(8)).
          /net/dns      The communications point for the Domain Name
                        Server, ndb/dns (see ndb(8)).

そして、その地図が現実にはどうなってるか確認出来る。下記も、一部を抜粋したもの。

term% ns
bind  /root /root
mount -aC '#s/boot' /root
bind  / /
bind  /386/bin /bin
bind -a /rc/bin /bin
bind  /net /net
bind -a '#l' /net
mount -C '#s/boot' /n/other other
bind -c /n/other/usr/glenda/tmp /usr/glenda/tmp
bind -c /n/other/usr/glenda/tmp /tmp
bind -a /usr/glenda/bin/rc /bin
bind -a /usr/glenda/bin/386 /bin
mount  '#s/rio.glenda.457' /mnt/wsys 1
mount -b '#s/rio.glenda.457' /dev
bind  /net/tcp/1/data /dev/cons
cd /usr/glenda

xxx/binを/binにかぶせてしまうので、/binをアクセスするだけで、必要な実行ファイルを全て手中に出来るという仕掛けなんだな。これを見て、以前入れたfindを/usr/glenda/bin/386の 下に移動しといた。これで、findって叩くだけで、何処にいても利用出来る。

上の地図を使って、面白い物を発見。

term% cat /adm/users
-1:adm:adm:glenda
0:none:adm:
1:tor:tor:
2:glenda:glenda:
10000:sys::glenda
10001:map:map:
10002:doc::
10003:upas:upas:glenda
10004:font::
10005:bootes:bootes:

このファイル、どうやらunixで言う、/etc/passwdと/etc/groupを兼ねたものらしい。 uid:user-name:group-name:add-group こんな意味を持ってるのかな。

sshfs

ふとした事からsshfsなんてのを知った。NFSの現代風なやつである。NFSだと管理者が厳格に 管理するんだけど、sshfsは通信にsshを使う、ユーザーが勝手に相手先の任意な場所を、手元の任意な場所に見せる事が出来る。市場開放と言うか規制緩和策である。

FreeBSDだとportsになってるんで fuse-sshfsを入れるだけ。但し使うまでにちょっとした 前準備が必要。

[fb11: kernel]$ sudo kldload fuse
[fb11: ~]$ sudo sysctl vfs.usermount=1
vfs.usermount: 0 -> 1
[fb11: ~]$ sshfs sakae@debian: /home/sakae/linux
[fb11: ~]$ ls linux/
ALL     GZ/     bsd/    qhs/    src/
[fb11: ~]$ df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
/dev/da0s1a  30450744  9715788 18298900    35%    /
devfs               1        1        0   100%    /dev
tmpfs         3597392        4  3597388     0%    /tmp
/dev/fuse    31347568 15361392 14370768    52%    /usr/home/sakae/linux
[fb11: ~]$ umount /usr/home/sakae/linux

ユーザーレベルのファイルシステム(fuse)が下敷きになるんで、モジュールをロード。ユーザーがマウント出来るように許可。手元(使うユーザーが読み書き出来るdir、この場合はlinux)に マウントポイントを用意。後はsshfsを実行。ネットの向こうにあるdebianのhomeがlinuxに現れた。使い終わったらumount。

リナちゃんだと、もう少し簡便で、ただ使うだけ。下記の場合はTop-dirを丸ごとbsd配下に 晒す事になる。

deb9:~$ sshfs sakae@freebsd:/ /home/sakae/bsd

なんだか、plan9ぽくないかい。

年の終わりのお約束

Qiita Advent Calendar 2017

そして、こちらは、お正月のお楽しみ用かな。

システムコールの追加

今年の更新は、これにて終了。来年も宜しくお願い致します。