理系学生日記

おまえはいつまで学生気分なのか

シェルにリダイレクト機能をつけた

シェルにリダイレクト機能をつけるというのは,わりかし楽だったりします.

リダイレクトの仕組み

まず前提としてあるのは,シェルは普通,fork によって子プロセスを作り,子プロセスが exec を呼び出してプログラムをロードし,実行するということです.ここで exec によってロードされるプログラムというのは,標準入力からデータを読み出し,標準出力と標準エラー出力にデータを書き込むようにプログラムされている.言い変えると,これらプログラムはファイルディスクリプタ 0 番からデータを読み出し,ファイルディスクリプタ 1 番と 2 番にデータを書き込むようになっている.ということは,exec を呼び出す前に,これらのディスクリプタをファイルにつなぎ変えてやれば良いということになります.

dup2 は第二引数として渡されたファイルディスクリプタが開かれていたらクローズした後で,第一引数のディスクリプタを第二引数のディスクリプタにコピーするシステムコール.これを使えばとりあえずできるので,まぁこんな感じじゃなかろうか.

void Shell::child() {
  // 子プロセスが実行するコード

  // [io]_fd は前段階でオープンしたファイルディスクリプタ
  if ( i_fd != STDIN  ) dup2( i_fd, STDIN  );
  if ( o_fd != STDOUT ) dup2( o_fd, STDOUT );

  execvp( *args, args );
  perror( *args );
  exit( 1 );
}

これでとりあえず,リダイレクトを処理できる.