自作シェルの進捗(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というスクリプトを標準入力から受け取ると、まずbashcatをfork-execして実行します。そして、catのプロセスが標準入力から文字を取り込むので、catの出力としてOHが出力されます。これが自作シェル(sush、寿司シェル)で動かない。OHsushが読み込んで、「そんなコマンドない」と叱ってきます。お前が読み込むからあかんのだが。

 いろいろ原因を探ってたのですが、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に倍増しました。

ということで、地道にBashに近づけてますので、もしよろしければ応援お願いいたします。

現場からは以上です。

ノート   このエントリーをはてなブックマークに追加 
 

prev:自作シェルの進捗(2025年4月15日) next:自作シェルの進捗(2025年4月25日)

やり散らかし一覧

記事いろいろ