Logo address

Unix port of rc

2023/08/06

はじめに

Ubuntu を動かしていた PC が壊れた。OS をインストールしていた HD も動かない(dead!)。
結局、余っていた HD に、新規インストールすることにした。この際、Rc に関して、いろいろ新たに気がついたことあり。以下に纏めておく。

インストールした Linux/Ubuntu のバージョンは

5.19.0-50-generic
Ubuntu 22.04.2 LTS
であった。Desktop 版ゆえ、サーバー用のソフトは全て自分でインストールしなくてはならない。コンパイラも!

以下は Rc に関した記事である。

Rc is designed by Tom Duff for Plan9 shell

[1] Tom Duff: Rc -- The Plan 9 Shell
https://www.scs.stanford.edu/nyu/04fa/sched/readings/rc.pdf

僕の過去記事:

Rc in unix

次の3つの Rc が unix で使える。
以下での名称 出処
Byron-rc by byron 注1
Russ-rc from p9p
Cinap-rc from 9front
Plan9-rc refers original rc for plan9


注: Byron の Rc は、apt-get でインストールすれば、man page も一緒に インストールされる。
ネットでも見れる:
[2] https://manpages.debian.org/unstable/rc/rc.byron.1.en.html

Command syntax

There are small difference in the command syntax.

Byron-rc

if(list) command;

if(list){
	command
} else command;

Plan9-rc

if(list) command;

if(list) command
if not command;

初めて Rc に触れたときに(おそらく)誰でも戸惑うことの一つは else が無いことだろう。Byron は率直に else を導入している。この問題では、Russ と Cinap は Plan9-rc を踏襲している。

Cinap-rc は 9front での拡張を含む。

Return status

Plan9 processes returns string status.

unix processes returns only integer status.
unix における rc が何を返すべきか、悩むところですね。実行環境に忠実であるとすれば、Byron-rc あるいは Cinap-rc になる。Plan9 の Rc スクリプトの移植を重視すれば Russ-rc になる。

Byron-rc:

0 in success
none zero in failure
Russ-rc
'' in success
none zero in failure
Cinap-rc
0 in success
none zero in failure

Installation

Plan9 の C コードを移植を考えると unix のコンパイラは clang が推奨される。gcc だと不必要な warning の山になる。clang の方が Plan9 の C コンパイラとの相性が良い。

Byron-rc

Linux では

apt-get install rc
で手に入る。/usr/bin/ にインストールされる。Ubuntu では /bin/usr/bin へのリンクになっている1。本体は /usr/bin/rc.byron としてインストールされている。/usr/bin/rc はそこへのリンクである。他の Rc (Russ-rc や Cinap-rc) を持っていれば
unlink /usr/bin/rc
でリンクを外しておかないと混乱する。(いざとなれば rc.byron で使える)

Russ-rc

P9P(Plan9port) に含まれている。P9P のコンパイルは結構な仕事である。

P9P は現在では Russ の手を離れて

https://9fans.github.io/plan9port/
に置かれている。メンテに問題ある。2020 年の P9P のコードは酷かった。2021 年のは問題点は修正されていた。それでも全てをコンパイルするのは、僕はギブアップした。

Cinap-rc

Cinap の Rc は unix に移植しやすいように工夫されている。9front の配布の中に含まれている。

/sys/src/cmd/rc
を unix にコピーする。ここには unix 用の Makefilercmain.unix が含まれている。

すんなりコンパイルできるはずである。

sudo make install
でコンパイルされた rc
/usr/local/bin
に、rcmain.unix のコピーの rcmain
/usr/local/lib
にインストールされる。


注1: /bin/usr/bin を区別しない気持がよく解らないのだ。僕の感覚では、/bin はオフィシャルな場所、/usr/binapt-get などによる準オフィシャルな場所な場所、/usr/local/bin はホストの運営者が責任を持ち、 Linux 関係者は責任を持たなくてもよい場所、$HOME/bin は、エンドユーザーの勝手。
安全に運用できるためには、ソフトの置き場所と管理責任を明確にすることが要求される。このことは unix のコンセプトに含まれていたはずであるが、最近はどうした訳かチャラチャラしている。

Execution

2023/08/08 修正

Cinap の Rc は最初に /usr/local/lib/rcmain を見に行き、次に $HOME/.rcrc を見に行く(存在すれば)。これは $HOME/.bashrc のような存在である。unix 用の $PATH を Rc に引き継ぎたければ(殆どの場合、そうであろう)、ここに

path=`{echo $PATH|sed 's/:/ /g'}
を含めておく必要がある。ただし、これを読ませるには "lflag" (load ?)
rc -l
が必要である。これは間違えやすく面倒だと思う。そこで僕は次のように /usr/local/lib/rcmain を変更している。今までのところ、これで問題はなさそう。実行時のコマンド検索パスは $HOME/.rcrc で設定しましょうとの考えに立っている。

# rcmain: unix version
if(~ $#home 0) home=$HOME
if(~ $#ifs 0) ifs='
'
profile=$home/.rcrc
switch($#prompt){
case 0
	prompt=('% ' '	')
case 1
	prompt=($prompt '	')
}
if(~ $rcname ?.out) prompt=('broken! ' '	')

fn sigexit

if(flag p) path=/bin
if not {
	finit
	if(~ $#path 0) path=(/bin /usr/bin /usr/local/bin)
	# it will be better not include '.' here.
}
# then we can use: echo and sed in $profile without "/bin/" prefix
if(/bin/test -r $profile)
	. -q $profile

if(! ~ $#cflag 0){
	status=''
	eval $cflag
}
if not if(flag i){
	status=''
	if(! ~ $#* 0) . $*
	. -i /dev/fd/0
}
if not if(~ $#* 0) . /dev/fd/0
if not{
	status=''
	. $*
}

修正後の /usr/local/lib/rcmain

これによると rc -p で実行した場合には /bin だけが検索パスになる。これは最も厳格な立場である。-p を添えない場合には (/bin /usr/bin /usr/local/bin) が検索パスである。Ubuntu では /bin/usr/bin へのリンクであるから、実際に使用されているのは2つだけである。/usr/local/bin の内容が吟味されていれば、かなり厳格な立場であると言える。これでは使いにくいなら $HOME/.rcrc を追加する。

#path=`{echo $PATH|sed 's/:/ /g'}
path=($PLAN9/bin $path .)

/usr/local/lib/rcmain

Plan9port がインストールされていれば、$PLAN9/bin を検索パスに入れた方が良いだろう。
2つのうちのどちらを採用するかは、あるいは他の方法をとるかは、ユーザーに任せる立場である。

Rc はスクリプト言語として設計されている。従って Rc が想定するインプットは人間ではない。
人間であれば、行編集機能が必要であるが、この機能を持たない。従ってキーの打ち間違いは許されない。
行編集機能は "rlwrap" が追加してくれる。行編集機能が必要なら

rlwrap rc
として実行すればよい。僕は長ったらしい名前は嫌いで、"rlwrap" --> "his" にしている。

rlwrap の下で emac key:

などが使える。("^" は control key)
矢印キーも。

なお Ubuntu には(僕が愛した初期の頃の) Emacs にそっくりのエディタ Jove が存在する。

sudo apt-get install jove
でインストールできる。

Emacs keybinding に関する記事:
[3] https://www.insource-da.co.jp/column/200226b.html

Plan9port

ここでは Plan9port に関係する範囲で、Linux における Clang の利用に関した問題を扱う。

Download

Plan9port の作成者は Russ Cox であるが、保守は David du Colombier に任せられている。
download site [4] には

using git: git clone https://github.com/9fans/plan9port plan9
latest tree: plan9port-master.zip (list of recent changes; license)
とある。git は共同開発者が使うツールである。普通の人は、plan9port-master.zip をダウンロードするが良い。

plan9port を展開したディレクトリを以下では $P9P とする。/usr/local/plan9 は避ける。

Compile and Installation

Clang によるコンパイルを推奨する。そのために $P9P/bin/9c を少し修正する:

*Linux*)	useclang
		#usegcc
これで Linux については Clang を使ってコンパイルされる1

グラフィックスに関係したコードのコンパイルは成功しないので避ける2。成功させるにはグラフィックスに関係した深い知識が要求され、これはこれで大仕事である。

$P9P/src/cmd にある次の4つが問題である。

現在の Ubuntu は X11 を使っていない。同じ問題は MacOS でも発生している。

これらのコンパイルを避けるには

mv devdraw .devdraw
のように、"." から始まる名前にする。

以上の下準備が完了したら、$P9P に移って

./INSTALL
を実行する。

Plan9port の正式な置き場所は

/usr/local/plan9
である。しかし、ここに直接 Plan9port のソースコードを置くと、アップデートの時に困る。そこで /usr/local/plan9 にインストールしたかのように OS に見せる:
ln -s $P9P /usr/local/plan9
もしも /usr/local/plan9 が存在すれば削除しておく。
unlink /usr/local/plan9
が無難。

$HOME/.bashrc あるいは $HOME/.profile に環境変数 PLAN9$PLAN9/bin へのパスを追加しておく。

PLAN9=/usr/local/plan9 export PLAN9
PATH=$PATH:$PLAN9/bin export PATH
.bashrc.profile とでは効果が少し異なる。

$P9P/ndb/local に好みのネットワークノードを追加する。形式は Plan9 の /lib/ndb/local と同じである。


注1: gcc から clang への変更について、
% ls -l /bin/cc
lrwxrwxrwx 1 root root 20  8月  2 13:34 /bin/cc -> /etc/alternatives/cc
% ls /etc/alternatives/cc
/etc/alternatives/cc
% ls -l /etc/alternatives/cc
lrwxrwxrwx 1 root root 12  8月  2 13:34 /etc/alternatives/cc -> /usr/bin/gcc
%
となっているので、gcc ではなく clang に変更する他の方法もあろうが、標準と異なる方法を採るときにはできるだけ影響を限定するのが基本的な考え方である。
注2: Ubuntu 22.04.2 LTSでは X11 がまだ使えるようなので大丈夫かもしれない。Try yourself! 僕は、昔 MacBook でインストールした方法をそのまま使った。MacOS の Aqua は手に負えなかったのだ。

Refs

[4] Plan 9 from User Space
https://9fans.github.io/plan9port/