scsh

Table of Contents

reinstall OpenBSD 7.4

前回WSL2を導入したら、VirtulBoxに入れていたOpenBSDが起動途中にハングす る様になった。VBに見切りをつけて、VMWare Playerに再インストールする事 にした。

bsd.mp

インストール時にうっかりしてて、シングルCPU構成でおこなってしまった。 後でそれに気がついて、どうやってマルチCPUにするんだと悩む。再度インス トールかな? まて、bsd.mpを入れれば、どうにかなるか? /etc/rcあたりに、 切り替え用のスイッチでも用意されてる? どちらも外れ馬券。

/usr/src/distrib/miniroot/install.sub

chmod og-rwx /mnt/bsd{,.mp,.rd} 2>/dev/null
if [[ -f /mnt/bsd.mp ]] && ((NCPU > 1)); then
        _kernel=$_kernel.MP
        echo "Multiprocessor machine; using bsd.mp instead of bsd."
        mv /mnt/bsd /mnt/bsd.sp 2>/dev/null
        mv /mnt/bsd.mp /mnt/bsd
fi

と言う事で、手動でやったよ。これで無事にマルチCPUになった。

reorder libc

起動中に、libc,crypt,sshd等の再配置が実行されている。これにより、boot時間が 延長される。何とかしたいぞ。そうだ、/etc/rcを見ればいいんだ。

# Re-link libraries, placing the objects in a random order.
reorder_libs() {
        local _error=false _dkdev _liba _libas _mp _ro_list _tmpdir
        local _relink=/usr/share/relink

        [[ $library_aslr == NO ]] && return
          ;
}

# Read output of reorder_libs co-process and output on console.
wait_reorder_libs() {
        local _line

        [[ $library_aslr == NO ]] && return

        while IFS= read -p _line; do
                echo -n "$_line"
        done
        echo
}

reorder_libs 2>&1 |&

sh /etc/netstart
start_daemon unwind >/dev/null 2>&1
random_seed

wait_reorder_libs
 :

こんな具合に、並列実行する様に改良されてた。少しはsystemdみたいになっ たな。夢々、systemdなんてのは導入しないで下さい。

で、これを禁止するには、/etc/rc.conf.localに、libraryaslr="NO" を追加 しておくと良い。デフォは

ob$ grep YES /etc/rc.conf
# set the following to "YES" to turn them on
pf=YES                  # Packet filter / NAT
check_quotas=YES        # NO may be desirable in some YP environments
library_aslr=YES        # set to NO to disable library randomization

coprocess

上で出てきたcoprocessの動作が良く理解できなかったので、実験コードを作 成してみた。reorderは仮に重い処理として4秒の時間浪費。main動作として、 2秒を指定。最後の1秒は、その他の雑多な処理。

#! /bin/sh

reorder_libs() {
    echo start reorder
    sleep 4
    echo end reorder
}

wait_reorder_libs() {
        local _line

        echo start wait
        while dmy= read -p _line; do
                echo "$_line"
        done
        echo end wait
}

reorder_libs ###  2>&1 |&

echo main work
sleep 2
echo main work end

wait_reorder_libs

sleep 1
echo all done

最初は、rcを模して並行動作(コメント無し)。

ob$ time ./rc.sh
main work
main work end
start wait
start reorder
end reorder
end wait
all done
    0m05.15s real     0m00.00s user     0m00.10s system

こちらは、コメントを有効にした。並行実行無し。

ob$ time ./rc.sh
start reorder
end reorder
main work
main work end
start wait
./rc.sh[25]: read: -p: no coprocess
end wait
all done
    0m07.22s real     0m00.00s user     0m00.17s system

折角エラー・メッセージを出してくれているんで、その現場をチェック。

ob$ pwd
/usr/src/bin/ksh
ob$ fgrep 'no coprocess' *
io.c:           *emsgp = "no coprocess";
ob$ grep emsgp *
io.c:check_fd(char *name, int mode, const char **emsgp)
io.c:                   if (emsgp)
io.c:                           *emsgp = "bad file descriptor";
io.c:                   if (emsgp)
io.c:                           *emsgp = (fl == O_WRONLY) ?
io.c:           return coproc_getfd(mode, emsgp);
io.c:   if (emsgp)
io.c:           *emsgp = "illegal file descriptor name";
io.c:coproc_getfd(int mode, const char **emsgp)
io.c:   if (emsgp)
io.c:           *emsgp = "no coprocess";

man sh じゃなくて、man ksh したら、しっかりと説明されてた。ほぼOpenBSD 固有の機能かな。

Co-processes
  A co-process, which is a pipeline created with the `|&' operator, is an
  asynchronous process that the shell can both write to (using print -p)
  and read from (using read -p).  The input and output of the co-process
  can also be manipulated using >&p and <&p redirections, respectively.
   :

serial

安心の為に、シリアル接続できる様にしておく。だって、VMWareのコンソールっ て窓がとっても小さいから。

VMWareの編集からシリアルを追加。名前付きパイプ \\.\pipe\mypipename この端末はサーバーです。接続先はアプリです。起動時に接続をONにする。 対する端末は、TeraTermです。シリアル接続がパイプからって、願ってもない 機能がサポートされてるからね。代替えの端末って存在するのだろうか? 肩 身の狭い世の中だのう。

OpenBSD側は、FAQになってた。ほかの機能も要点が良くまとめられていて好感。

Configuring a Serial Console

ielm vs eshell

eshellって便利。たとえば、emacs –help とか ruby –help なんてやると、ズラッとヘルプが 表示される(man emacsなんてのは時代遅れなんだな)。前の方を見たいなら、今迄なら、tmuxとかの画面戻るぞを使った りしてたんだ。

それが、eshell上なら、かまわず、emacs –helpしちゃえ。やおら、C-c v し て、view modeに変更しちゃう。そしたら、space/backspace と言う特大 key(英語配列ですけど)で、前進したり後退したりが自在。view modeの解除は、 もう一度 C-c vするだけ。

(global-set-key   "\M-," 'pop-tag-mark)     ;; replace M-*
(define-key mode-specific-map "c" 'compile) ;; C-c c to compile
(define-key mode-specific-map "v" 'view-mode) ;; C-c v to toggle view-mode
(define-key mode-specific-map "g" 'goto-line) ;; goto line

その他、こんなキーマップを割り当てている。

もう一つ便利なのが、cat fact.el とかして、内容を表示。それをコピペ出来 ちゃう事(勿論、M-w C-yの定番キー操作ね)。後はRETすれば、S式が評価され る。eshellと言いつつ、emacs専用のREPLである、ielm を兼ねているよ。

んな訳で、今日からは、eshellを多用すべし。幸いにも、ielmの遅いモードを 脱却できている(下記の比較(以前やったベンチマーク)を参照)。

(11.260014140000001 125 7.600907907)   ;; on ielm
(2.605592303 4 0.178970314)            ;; on eshell
(2.522473842 3 0.133453492)            ;; on ksh

scsh

eshellでelispを走らせる事が分かった。ならば、schemeでも出来るはず。そ んなのgoshとかでいいじゃん。まて、それ用にチューニングしたアプリが有っ たはず。

SCSH(Scheme Shell)スクリプト入門

scsh.net

scsh manual

ワーニング多数、エラーが2箇所を乗り越えて起動。

ob$ ./go
Welcome to scsh 0.6.6 (King Conan)
Type ,? for help.
> (define hello "Hello world")
> hello
"Hello world"
> (date)
'#{%date}
> (time)
1704869327
> (date->string (date))
"Wed Jan 10 15:49:59 2024"
> (pid)
99083
> (cwd)
"/tmp/scsh-0.6.6"

で、goの正体は?

ob$ cat go
#!/bin/sh

lib=/tmp/scsh-0.6.6
exec $lib/scshvm -o $lib/scshvm -i $lib/scsh/scsh.image "$@"

scshvmがイメージを動作させるって塩梅なのか。これ、コンパイルした時の チェック用。インストールすれば、scshで利用できる正式版になる。

ああ、そそっかしい事に版が古かったので、最新版で確認。

ob$ ./go
Welcome to scsh 0.6.7 (R6RS)
Type ,? for help.
> (pid)
11619
> (cwd)
"/tmp/scsh-0.6.7"

schemeが一つ欲しいと思っていたので、/opt/bin/scshに鎮座させた。

scheme48

scshの土台は、 Scheme48 だ。広告には、

Scheme 48 is an implementation of the Scheme programming language as
described in the Revised^5 Report on the Algorithmic Language Scheme.
It is based on a compiler and interpreter for a virtual Scheme
machine.  The name derives from our desire to have an implementation
that is simple and lucid enough that it looks as if it were written in
just 48 hours.  We don't claim to have reached that stage yet; much
more simplification is necessary.
Scheme 48 is an implementation of the Scheme programming language as described
in the Revised5 Report on the Algorithmic Language Scheme [6]. It is based on
a compiler and interpreter for a virtual Scheme machine. Scheme 48 tries to be
faithful to the Revised5 Scheme Report, providing neither more nor less in the
initial user environment. (This is not to say that more isn't available in
other environments; see below.)

頑張って48時間で書いたからねってのが由来のようだ。組み込み用にeclって 言うCommonLispが有って、その上にmaximaと言う数式処理システムが構築され てるのと、同じ構図だな。小さいのは良い事だ。隅々まで目がいくからね。

マニュアルをチラ見してたら、楽しいコマンドを発見

> ,dis cons
cons
  0 (protocol 2)
  2 (pop)
  3 (make-stored-object 2 pair)
  6 (return)
> ,dis car
car
  0 (protocol 1)
  2 (pop)
  3 (stored-object-ref pair 0)
  6 (return)
> ,dis list
list
  0 (protocol 0 +)
  4 (make-env 1)
  7 (local0 1)
  9 (return)

なんとなくVMの作りが想像できる。楽しいシステムだな。 そして、Mixing Scheme 48 and C こんなのもある。 emacsだと、前回だからに、ダイナミック・モジュールに相応するのかな。 憧れの The Scheme (by cisco) にも、同様な物が公開されてた。

Access to POSIX こんなのも有って、scshの基礎になってるんだな。 後は、scheme48にデコレーション(regex とか awk機能、更にnetworking機能)すれば、いいだけ。

核心は、/opt/src/scsh-0.6.7/scheme/vm/arch.scm

scheme48 on ArchLinux

ふと思いたって、64Bitでも動くか確認。いきなりのgdbって所がアレゲです が。。

[sakae@arch scheme48-1.9.2]$ gdb -q scheme48vm
Reading symbols from scheme48vm...
(gdb) b main
Breakpoint 1 at 0xb770: file ./c/main.c, line 15.
(gdb) r -i scheme48.image
Starting program: /tmp/scheme48-1.9.2/scheme48vm -i scheme48.image
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Breakpoint 1, main (argc=3, argv=0x7fffffffe988) at ./c/main.c:15
15        return_value = s48_initialize(&argc, &argv);

goなんて動かないので、分解してバーチャル・マシンをgdbの餌食にします。 餌はイメージ・ファイル。

(gdb) s
s48_initialize (argcp=argcp@entry=0x7fffffffe86c,
    argv=argv@entry=0x7fffffffe860) at c/init.c:62
62        int argc = *argcp;
(gdb) finish
Run till exit from #0  s48_initialize (argcp=argcp@entry=0x7fffffffe86c,
    argv=argv@entry=0x7fffffffe860) at c/init.c:62
main (argc=<optimized out>, argv=<optimized out>) at ./c/main.c:17
17        if (return_value != 0)
Value returned is $1 = 0
(gdb) l
12      {
13        long return_value;
14
15        return_value = s48_initialize(&argc, &argv);
16
17        if (return_value != 0)
18          return return_value;
19        else
20          return s48_call_startup_procedure(argv, argc);
21      }

メインはさっぱりしたものです。

(gdb) c
Continuing.
Welcome to Scheme 48 1.9.2 (made by sakae on 2024-01-14)
See http://s48.org/ for more information.
Please report bugs to scheme-48-bugs@s48.org.
Get more information at http://www.s48.org/.
Type ,? (comma question-mark) for help.
>
Exit Scheme 48 (y/n)? y
[Inferior 1 (process 20834) exited with code 01]
(gdb) q
[sakae@arch scheme48-1.9.2]$ fgrep 'Exit Scheme 48' -r .
fgrep: warning: fgrep is obsolescent; using grep -F
./scheme/env/command.scm:             ((y-or-n? "Exit Scheme 48" #t)

動いたな。で、終了の問い合わせについて、問い合わせ。徹底的にscmになっ てるんですねぇ。ならばTAGSファイルを作成できるかな。

[sakae@arch scheme48-1.9.2]$ make tags
find . -name "*.scm" -o -name "*.c" -o -name "*.h" | etags -

やや、gdbinitが有るぞ。

#
# Commands useful for debugging the Scheme48 VM.
#

#Set a breakpoint at label "raise".
#Obtain the proper line number using "egrep -n raise: scheme48vm.c".
break scheme48vm.c:5227

display/i $pc
 :

raise: に網を貼っておくといいよ、と読めるんだけど、家捜ししてもそんな 語句はヒットせず。このファイル自体が、かなり昔のもので、その後のメンテ ナンスがされていないな。これは、作者さんからの挑戦状かしらん。

32bitなOpenBSDに舞台を移して、挑戦してみようかしらん。

make log

scheme48の実行環境が作成されるまでのログ・ファイルあらまし。

 :
fake/glue.o c/fake/glue.c
rm -f c/libscheme48.a;                                                  \
ar cq c/libscheme48.a c/scheme48vm-32.o c/extension.o c/free.o c/double_to_stri\
ng.o c/bignum.o c/ffi.o c/external.o c/external-lib.o c/external-init.o c/init.\
o c/scheme48-bibop-heap-32.o c/bibop/page_alloc.o c/bibop/memory_map.o c/bibop/\
areas.o c/bibop/generation_gc.o c/bibop/find_all.o c/bibop/check_heap.o c/bibop\
/utils.o c/bibop/area_roots.o c/bibop/remset.o c/unix/misc.o c/unix/io.o c/unix\
/fd-io.o c/unix/event.o c/unix/time.o  c/net/socket.o c/net/address.o c/net/net\
.o c/unix/socket.o c/unix/dynlink.o c/unix/sysexits.o c/fake/glue.o
ranlib c/libscheme48.a

gcc -rdynamic -pthread  -g -O2 -pthread  -o scheme48vm c/main.o c/libscheme48.a\
 -lnsl -ldl -lm

./build/build-usual-image . \
        "`(cd . && pwd)`/scheme" "`pwd`/c" 'scheme48.image' './scheme48vm' \
        './build/initial.image-32'
./scheme/env/init-defpackage.scm
#{Unspecific}
./scheme/packages.scm
./scheme/more-interfaces.scm
 :
[display-conditions ./scheme/env/dispcond.scm]
[command-levels ./scheme/env/user.scm ./scheme/env/command-level.scm]
[disclosers ./scheme/env/disclosers.scm]
 :
[usual-features]
#{Unspecific}
Reading ./build/initial.debug
#{Unspecific}
#{Unspecific}
#{Unspecific}
Writing scheme48.image
 :
gcc -o c/srfi-27.so  c/srfi-27.o -shared  -rdynamic
gcc -o c/ffi-test.so c/ffi-test/ffi-test.o -shared  -rdynamic
gcc -o c/r6rs.so c/r6rs/ieee_bytevect.o c/r6rs/r6rs_externals.o  -shared  -rdyn\
amic

build/build-usual-image (shell script)

srcdir=$1
share=$2
lib=$3
image=$4
vm=$5
initial=$6
USER=${USER-`logname 2>/dev/null || echo '*GOK*'`}

$vm -i $initial -a batch <<EOF
,load $srcdir/scheme/env/init-defpackage.scm
((*structure-ref filenames 'set-global-translation!)
 "=scheme48/" "$srcdir/scheme/")
,load =scheme48/packages.scm
,load =scheme48/more-interfaces.scm
 :
(set-global-translation! "=scheme48external/" "$lib/")
,user
,build ((*structure-ref package-commands-internal
                        'new-command-processor)
        "(made by $USER on $date)"
        usual-commands
        built-in-structures more-structures) $image
EOF

debug emacs -batch

バッチモードなら、楽しく観察できるに違いない。

emacs -batch -l /tmp/mytest.el

(gdb) bt
#0  command_loop () at keyboard.c:1111
#1  0x0057ca34 in recursive_edit_1 () at keyboard.c:744
#2  0x0057cc06 in Frecursive_edit () at keyboard.c:827
#3  0x00578f71 in main (argc=4, argv=0xbffff584) at emacs.c:2625

相変わらず、闇は深いな。

ArchLinux X11

前回の遊び WSL2で、WSLg が、後遺症を残していないか心配。そこで、 OpenBSDのgnuplotでWindows10側にちゃんとグラフを表示してくれるか、確認 する。 自前でgnuplotをコンパイルするのも、かったるいので、pkgから入れた。 ちゃんと描画した。

ArchLinuxはどうか? やはりエラーだ。新ためてぐぐったら、mesaが悪いなんて話が出てた。ならば、改良版 が出てないか? pacman -Syu したら、 mesa-1:23.3.2-2 が、含まれていた。

かくして、ちゃんと動くようになった。基幹の奴でも大チョンボする事が有る のね(だって、人間だもの)。


This year's Index

Home