jot

地区の回覧板に、『立川談志さんの落語の会』なんてご案内が載ってた。あれれ? 談志さんて もう他界しちゃってるよな、弟子が襲名でもしたんかな。いずれにせよ、参加無料、場所も家から 歩いて10分もかからない所。たまに馬鹿笑いするのもよかろうと思ったわけだ。

当日は朝から晴天、小春日和で散歩にはうってつけ。少し遠回りして行ってみた。座敷にお茶と 菓子と漬物とリンゴが用意されてた。地区のおばあさんが続々と集まって来る。男は主催者の 方を除いておいら一人。おまけに、座敷の床の間には、デンと大型ディスプレーが鎮座してる。

ああ、騙されたな。落語が大体朝の9時半から始まるなんて聞いた事ないぞ。密かに撤退しよう かと、思ったり思わなかったり。。そんなおいらの心情を察知してか、おそろいの派手なジャンバーを 着たおばさんが、目の前の茶碗にお茶をついでくれちゃったよ。こりゃ、撤退は諦めて、笑って 帰ろう、となっちゃいました。

開始まで少し時間が有ったので、ジャンパーのおばちゃんに聞いてみた。そのおそろいのジャンバー、 談志さんのファンクラブか何かのものですか? 我ながら変な質問だな。そしたら、そのおばちゃんは、 地区の保健婦さんなんですって。そうか、それで合点がいったよ。

家にいる老人をこういう催しにひっぱり出して、多いに笑ってもらおうって事なんだな。

隣に座ったおばちゃんに一応挨拶。農家の仕事(りんご、ぶどう、田)の仕事が一段落しつつ あるので、気晴らしに来たとか。おじいちゃん、おばあちゃんで農業が出来るのは、トラクター やら消毒車とかで力仕事をしなくてもいいからとか。その代わり、それらの機械の購入費やら 維持費が馬鹿にならないってぼやきも。。 息子が嫁でも貰って後を継いでくれればと、言って ましたよ。

演題は、寝床と権現狸の二題。落語って聴くものとばかり思っていたけど、観るものなんですね。 笑点しか見た事ないおいらは、認識を新たにしましたよ。

後で、主催者から挨拶があり、落語のCDはそこそこあるけど、視聴出来るDVDはほとんど無い 事を知った。演舞場まで気軽に行けない地方の方向けにいろいろリリースして欲しいぞ。 もう、韓流は止めにして。

shellで乱数生成

以前、freebsd-updateしてる時に待ち時間があったので、そのソースを見てた。面白い コードが出てたのでWebにも取り上げておいたけど、もちっと詳しく調べてみるか。 ちなみに、こんなコードだった。

# Generate a random seed for use in picking mirrors.  If HTTP_PROXY
# is set, this will be used to generate the seed; otherwise, the seed
# will be random.
        if [ -n "${HTTP_PROXY}${http_proxy}" ]; then
                RANDVALUE=`sha256 -qs "${HTTP_PROXY}${http_proxy}" |
                    tr -d 'a-f' |
                    cut -c 1-9`
        else
                RANDVALUE=`jot -r 1 0 999999999`
        fi
}

どこが面白い? Perlやrubyやpythonやlispなんて言うそれなりの言語処理系を使わなくても、 乱数を生成する方法が2種類、展示されているからだ。

一つは、sha256って言う何処にもありそうなコマンド。もう一つは*BSD限定(かも知れない)なjot ってコマンド。jotの方は、今回初めて知ったコマンドだけど、これがまた面白そうなんだな。 順番に見て行こう。

sha256

結城さんの『不思議な国のアリス・暗号編』だったかを見ると、きっと載ってるよ。 ネットからファイルをDLした時等、そのファイルが正統なものであるかどうかの検査に 使う。気の利いたサイト(セキュリティー意識の高い所)には、これの検査値が置いてある。

もっと身近な例だと、gitかな。リナス君が頑張って開発して、あれよあれよと言う間に野火の ごとく世界征服しちゃったね。このgitにも確か使われていたはず。

[sakae@secd ~/mruby/.git/objects]$ ls 55
70d35f9b2eff0741a5bec1e641349ac2cba189  feb645c2c973c3901a9a9e811921282121d02d

mrubyをgitからcloneしてきたけど、ファイルの実体は、こんな訳わかめな名前になってる。こんな訳わかめな名前を どうやって生成してるかと言うと、sha256なり(同属のsha1コマンド)で作っているんだ。ファイルの内容が一文字でも 異なると、この訳わかめな名前が大幅に異なったものになるんだ。いわゆる、ファイルの指紋って訳。

今回は、この訳わかめをsha256に生成させ、その中から不要なa-fを取り除き、残った数字だけを 冒頭から9文字抽出してる。

sha256にオプションを与えると、ファイルだけじゃなくて、指定した文字列からも指紋が 生成出来るんだ。

[sakae@secd ~]$ sha256 -qs hoge
ecb666d778725ec97307044d642bf4d160aabb76f56c0069c71ea25b1e926825
[sakae@secd ~]$ sha256 -qs hogeX
46572136b70b7bd0575bd19b69d0f9839d42b0c6f35bbfa75afcc0c5ac814ed2

一文字違うだけで、指紋(ハッシュ値とも言う)は大幅に異なる。

[sakae@secd ~]$ sha256 -qs hoge
ecb666d778725ec97307044d642bf4d160aabb76f56c0069c71ea25b1e926825
[sakae@secd ~]$ sha256 -qs hoge | tr -d 'a-f'
6667787259730704464241607656006971251926825
[sakae@secd ~]$ sha256 -qs hoge | tr -d 'a-f' | cut -c 1-9
666778725

上記は、hoge って文字列を種にして、9桁の乱数を生成する過程だ。unixの文字列処理コマンドと パイプを上手に組み合わせて、目的を達している。

それじゃ、使う度に違う乱数値を返すようにするには、どうしたらいいか? 使う度に違う値って 事なら、日時がいの一番にうかぶな。例えばこんなの。

[sakae@secd ~]$ date "+%Y%m%d%H%M.%S"
201210271324.20

これを種文字にしてもいいんだけど、もう少し味付けをしたい。塩を足すって意味でSaltを加える なんていいますけど、この塩には、よくpidが使われる。

[sakae@secd ~]$ date "+%Y%m%d%H%M.%S-$$"
201210271330.56-1081

後は、上記の味付け日時を種に使ってあげるだけ。

[sakae@secd ~]$ sha256 -qs `date "+%Y%m%d%H%M.%S-$$"` | tr -d 'a-f' | cut -c 1-9
866123124
[sakae@secd ~]$ sha256 -qs `date "+%Y%m%d%H%M.%S-$$"` | tr -d 'a-f' | cut -c 1-9
397674930

freebsd-updateの中では、種として、HTTP_PROXY(http_proxy)の設定値が使われている。 そんじゃ、もう一つのjotは、どうなっているんだろう?

jot

面倒なので、manから引き写します。(宿題だと落第だな)

NAME
     jot ? print sequential or random data

SYNOPSIS
     jot [-cnr] [-b word] [-w word] [-s string] [-p precision]
         [reps [begin [end [s]]]]

DESCRIPTION
     The jot utility is used to print out increasing, decreasing, random, or
     redundant data, usually numbers, one per line.

     The following options are available:

     -r      Generate random data instead of the default sequential data.

実例をば、

[sakae@secd ~]$ jot -r 2 100 1000
857
195

これ、100から1000の間の乱数を2つ発生させなさいって指令です。もろに乱数発生器ですな。 でも、jotは説明にあるだけじゃなく、数列も発生できます。

[sakae@secd ~]$ jot 4 2 8
2
4
6
8

こちらは、2から8までの間を(等分にして)4つの数字を発生しなさいって事になります。うぃ、 こんなの、どこかで出くわした事あるよ。manをずっと辿って行くと、

     The name jot derives in part from iota, a function in APL.

ほー、APLってIBMの数学研究所で生まれた高尚な言語じゃないですか。それにiotaって何処かで 聞いた事があるような。。。

HISTORY
     The jot utility first appeared in 4.2BSD.

カリフォーニアの大学の香りがしますなあ。例も載ってて、面白いなあと思ったのは、

[sakae@secd ~]$ jot -r -c 120 A Z | rs -g 0 5 | rs 0 8
XESMY  VLMBO  QIEEC  CQZUK  CIYIP  OBGHN  YERQR  PLCBN
RSWVW  YYNXS  XABWI  QLJWS  WUXOL  PEWSF  KJXGE  UECIC
UGCVD  KMOUI  GRDDG  OTKLL  PVUNC  YIGAQ  IVXLR  AWDOQ

これ、前回やったモールス信号発生器の電文生成に使えるぞ。暗号の受信に最適。 意味は、AからZまでのASCII文字を120個発生しなさい。それをrsコマンドで受けて、5文字毎に 区切りなさい。それを8組並べなさい。行数は0って事で、この場合は制限無しって意味になります。

Linuxでも乱数

デフォでbashが入ってるはずだから、

[sakae@arch ~]$ echo $RANDOM
1200
[sakae@arch ~]$ echo $RANDOM
20047

こういう安易な方法でいいみたい。別な方法としては

[sakae@arch ~]$ od -vAn -N4 -tu4 < /dev/random
 1680855093
[sakae@arch ~]$ od -vAn -N4 -tu4 < /dev/random
  454376925

こういうのもあるそうです。デバイスに真の乱数発生器を接続すれば面白そう。だれか、ツェナーダイオードの アバランシュ効果(端的に言えば雑音)を使った発生器を作りませんかね。

Linuxで等差数列

Linuxには、高尚なjotコマンドは無いみたい。その代わり原始的なやつがある。

[sakae@arch ~]$ for i in `seq 1 4`; do echo $i; done
1
2
3
4

まあ、これで大概な用は足りると思うんだけど、jot を移植できないかな?

Linuxでもjotするぞ

FreeBSD側で、移植の前確認をしときます。まさか特殊な子分(ライブラリィー)は連れて いないよな。

[sakae@secd ~]$ ldd /usr/bin/jot
/usr/bin/jot:
        libc.so.7 => /lib/libc.so.7 (0x2806a000)

大丈夫そうなので、ソース系を確認

[sakae@secd /usr/src/usr.bin/jot]$ ls
Makefile        jot.1           jot.c

Makefileを持って行ってもしょうがないので、jot.cとjot.1のマニュアルだな。 持って行ってコンパイルすると、

[sakae@arch z]$ cc -g jot.c
jot.c:42:10: エラー: expected declaration specifiers or ‘...’ before string constant
// __FBSDID("$FreeBSD: releng/9.1/usr.bin/jot/jot.c 216370 2010-12-11 08:32:16Z joel $");

FreBSD特有のやつはお気に召さないようなので、コメントアウト

[sakae@arch z]$ cc -g jot.c
/tmp/ccOuM4GL.o: In function `main':
/home/sakae/z/jot.c:114: undefined reference to `strlcpy'
/home/sakae/z/jot.c:293: undefined reference to `strlcpy'
/home/sakae/z/jot.c:301: undefined reference to `arc4random'
/tmp/ccOuM4GL.o: In function `getformat':
/home/sakae/z/jot.c:410: undefined reference to `strlcpy'
/home/sakae/z/jot.c:487: undefined reference to `strlcat'
collect2: エラー: ld はステータス 1 で終了しました

strlcpyはFreeBSD特有っぽいので、strncpyに変える。(strlcatも同様)残るは、arc4randomだな。

     The arc4random() function uses the key stream generator employed by the
     arc4 cipher, which uses 8*8 8 bit S-Boxes.  The S-Boxes can be in about
     (2**1700) states.  The arc4random() function returns pseudo-random num‐
     bers in the range of 0 to (2**32)?1, and therefore has twice the range of
     rand(3) and random(3).

RSA社が作った暗号用の乱数発生器だ。jot.cの中では、

                        if (use_random)
                                y = random() / divisor;
                        else
                                y = arc4random() / divisor;

こんな使い方をしてて、-rを付けた時にuse_randomがtrueになる。取りあえず、RSA社には遠慮 してもらったよ。久しぶりにclangに登場願って コンパイルしてみると、

[sakae@arch z]$ clang jot.c
jot.c:114:48: warning: ordered comparison between pointer and integer ('char *' and 'unsigned int')
                        if (strncpy(format, optarg, sizeof(format)) >=
                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
jot.c:410:28: warning: ordered comparison between pointer and integer ('char *' and 'size_t' (aka 'unsigned int'))
                if (strncpy(p, "%c", sz) >= sz)
                    ~~~~~~~~~~~~~~~~~~~~ ^  ~~
jot.c:487:46: warning: ordered comparison between pointer and integer ('char *' and 'unsigned int')
                                if (strncat(format, "%", sizeof(format)) >=
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.

イエローカードだから、取りあえず見なかった事にしよう。/usr/local系にmanも含めてインストール したよ。

[sakae@arch ~]$ jot 4 5 20
5
10
15
20
[sakae@arch ~]$ jot  -wMyfile%04d.txt 4 4649
Myfile4649.txt
Myfile4650.txt
Myfile4651.txt
Myfile4652.txt

ちゃんと動いているよ。(と言うと、testはどうしたって、目くじら立てる人が居るに決まってるな。)

iota

manにはjotの元になったのは、iotaって書いてあったな。 私のかすかな記憶では、iotaってSchemeのsrfi-1に有ったはず。確認してみる。

gosh> (use srfi-1)
#<undef>
gosh> (iota 10)
(0 1 2 3 4 5 6 7 8 9)

どんなソースになってるかな? ~/Gauche-0.9.3.3/src/liblist.scmに有った。

(define (iota count :optional (start 0) (step 1)) ;srfi-1
  (when (< count 0) (error "count must be nonnegative: " count))
  (if (and (exact? start) (exact? step))
    (do ([c count (- c 1)]
         [v (+ start (* (- count 1) step)) (- v step)]
         [r '() (cons v r)])
        [(<= c 0) r])
    ;; for inexact numbers, we use multiplication to avoid error accumulation.
    (do ([c count (- c 1)]
         [r '() (cons (+ start (* (- c 1) step)) r)])
        [(<= c 0) r])))

これ、どう見たって、乱数の発生機能は組み込まれていないな。jotはiotaの進化系なんだな。

カンニングもとえ参照

上のiotaの一番簡単なのは、ただ個数を指定するだけ。Arch上に移植したjotでも動くんだろうな。 誰かさんに文句を言われないように、一番簡単なテストをしてみる。

[sakae@arch ~]$ jot
usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]
           [reps [begin [end [s]]]]
[sakae@arch ~]$ jot 3
%.0-1f
%.0-1f
%.0-1f

引数無しで使い方ってのは想定内だけど、引数一つの結果がおかしいな。ちゃんとテストは やってみるもんだ。どんなテストをすればいいかってのは指針があるんですかね? 教えて、うるさいい 、もとえ、詳しい人。

で、エラーが見つかったら何とかせんといかん訳だが、もうソースと格闘する元気が ありません。何処かにLinuxへ移植済みのソースがないかな。 困った時はどらえもんを頼りにする、のび太君に変身しちゃえ。

ドラエモンのポケットと化しているウブでjotを探してみます。

sakae@ubuntu:~$ apt-cache search jot
kjots - note-taking utility
athena-jot - print out increasing, decreasing, random, or redundant data, one per line
enum - seq- and jot-like enumerator
gjots2 - Simple jotter (outline processor) for X11/gtk-gnome
rhinote - virtual sticky-notes for your desktop

どうやら、athena-jotがそれっぽいので、お取り寄せ。一応コンパイルしてみます。

sakae@ubuntu:~/ubn-src/athena-jot-9.0$ make
gcc -c -I.  -g -O jot.c
gcc  -o jot jot.o -lbsd
/usr/bin/ld: cannot find -lbsd
collect2: ld returned 1 exit status
make: *** [jot] Error 1

あらら、bsdのライブラリーが必要なのね。おいらが誤魔化しちゃったstrlcpyとかは、bsdライブラリーに 頼っているのね。しゃーない、開いてみるか。

あら、NetBSDからソースを持ってきているよ。冒頭付近

#if defined(HAVE_BSD_STDLIB_H)
  #include <bsd/stdlib.h>
  #define random arc4random
#else
  #if !defined(HAVE_SRANDOM) || !defined(HAVE_SRANDOM)
    #if defined(HAVE_SRAND48) && defined(HAVE_LRAND48)
      #define srandom srand48
      #define random lrand48
    #else
      #define srandom srand
      #define random rand
    #endif
  #endif
#endif /* HAVE_BSD_STDLIB_H */

ベタで書かれたプリプロセッサ命令は分かりずらいので、ちょっとインデントした。randomを どうするって話だけですな。

自動生成されたconfig.hを見ると、HAVE_BSD_STDLIB_Hなんて定義されていないのに、Makefileでは、 lbsdをリンクしろって指示してる。こりゃ、移植した人のやっつけ仕事だな。

手動でコンパイルしたら、普通に動いちゃったぞ。ソースの方では、strlcpy とかは使われていない。

結論的には、FreeBSDは独自の進化を遂げているんで、ソースをLinuxへ持ってこようとすると 苦労する。持ってくるなら、NetBSDのそれにしとけ。

ここからはおいらの想像だけど、はじめNetBSDな人がjotを書いた。セキュリティーに五月蝿い親分が いる、OpenBSDに取り込む時に、いろいろセキュリティー面を改良した。何でも貪欲に取り込む FreeBSD陣営が、OpenBSDの版を移植した。麗しきBSD3兄弟だなあ。

好きい夢 (Scheme)

少々疲れたので、夢でもみましょ。

以前やった、SimpleってSchemeが強力になってます。Windows上で強力に動くようにチューニング されてますので、もう鼻歌交じりでunix上に持ってくるのが辛くなりました。

今後は、 好きい夢 (Scheme)のサイトを 見守っていきます。とってもいい名前ですね。