自作シェルの進捗(2025年4月25日)
Fri Apr 25 18:09:06 JST 2025 (modified: Fri Apr 25 18:49:14 JST 2025)
views: 100, keywords:自作シェル,rusty_bash,寿司シェル
前回(4月15日)からの進捗。
スクリプトとread
の読み込みをバッファなしにする
さっき取ったバグなんですが、こういう挙動の違いの差に悩んでました。
Bashの場合、cat改行OH
というスクリプトを標準入力から受け取ると、まずbash
がcat
をfork-execして実行します。そして、cat
のプロセスが標準入力から文字を取り込むので、cat
の出力としてOH
が出力されます。これが自作シェル(sush
、寿司シェル)で動かない。OH
をsush
が読み込んで、「そんなコマンドない」と叱ってきます。お前が読み込むからあかんのだが。
いろいろ原因を探ってたのですが、strace
してみたら、sush
のプロセスが入力を2行まとめてread
してしまってました。ファイルディスクリプタの操作を間違っているんじゃないかと思ってたら、案外単純でした。
んで、さらに調べたらRustの標準入力を1行読むやつ(std::io::stdin().read_line()
)が勝手に何行も読んでバッファリングしてました。いや、勝手にって書きましたがちゃんと https://doc.rust-lang.org/std/io/fn.stdin.html に書いてありますごめんなさいごめんなさい。
ということで、バッファリングしないようにしたらsush
でもBashの挙動が再現できました。パフォーマンスはちょっと落ちるような気がしますが、パイプ自体がバッファを持ってるのにシェル側でまたバッファを持つのもなんとなく変なので、これでいいと思います。
ただ、Rustでバッファなしで標準入力を扱う方法がよくわからず、結局、このクレートを使うことにしました。なんで先祖返りするためにクレートを追加せねばならぬのか分からん・・・のですが、過保護な言語にはよくある話ではあります。(たぶんクレートなしでもできます。)
インデックスを指定した配列、連想配列の初期化
私は絶対に使わない機能ですが、こういう書式に対応しました。配列のどこにデータを入れるか指定して配列を初期化(or 追記)する方法です。
連想配列でも動きます。私は絶対に使わないですが。
その他
${hoge[@]/a/b}
、${hoge[@]%%a}
など、配列の各要素を置換したり、削除したりする機能を実装し忘れていたので、実装を追加しました。また、ヒアドキュメントの実装が雑だったので少しまともにしました。現在のBashとの互換性テストはこんな感じです。前回から通ったテストスクリプトの数が7から14に倍増しました。
ここ数日実装漏れとかI/O関係の不備とかが次々と見つかって、Bashとの互換性テストの結果が一気に14/85(16%)まで向上しました #自作シェル #bashhttps://t.co/EmMlWYpeqi pic.twitter.com/CYtO9eVA4s
— 上田隆一 (@ryuichiueda) April 25, 2025
ということで、地道にBashに近づけてますので、もしよろしければ応援お願いいたします。
現場からは以上です。