第2回
exsh-2
下の順序でcatchとexsh-2を同じディレクトリに作成せよ.
- catchとexsh-2の両方をコンパイルするように,Makefileを変更すること.
- exsh-2はexsh-1を基にして作成すること.
1. 準備.
exsh-1を実行して"^C"を入力し,shやcshとの挙動の違いを比較せよ. shやcshは再度プロンプトを出力するが,exsh-1は自身が終了してしまうことを確認せよ.
2. シグナル処理の実験.
- "Zzz."を出力して1秒間sleep()することを永遠に繰り返すコマンドcatchを作成する.catchはシグナルハンドラを登録していないので,"^C"で中断できることを確認する.
- SIGINTを補足すると,"^C"で中断できないことを確認する. コマンドを実行したままでは困るので,端末から"^Z"を入力しサスペンドにして, killコマンドを用いて中断すること.
- 別なシェルからkillコマンドでSIGINTを送ってみる.
- 同様に,別なシェルからSIGKILLを送って中断を確認する.
- SIG_IGNでSIGINTを無視してみる.
- SIGUSR1にもシグナルハンドラを登録して,別なシェルからシグナルを送信してみる.シグナルの種類は"kill -l"で表示できる.
- SIGSEGVにもシグナルハンドラを登録して,意図的にsegmentation faultを起こしてみる.
3. exsh-2に引数処理を追加する.
- コマンド入力の引数解析を行ない,引数をexeclp()へ渡すこと.
- "ls"と"ls -l"を入力し,引数が正しくサブコマンドへ渡ることを確認すること.
注意: 引数解析はまじめにやると複雑なので,strtok()を使って空白で区切る程度で留めても良い.例えば,double quoteとsingle quoteの扱いなどは面倒である.ただし,引数の個数の上限検査は必要である.
また,
retval = execlp(args[0], args[0],
args[1], args[2], args[3], args[4],
args[5], args[6], args[7], args[8],
NULL);
を
retval = execvp(args[0], args);
のように書けるため,この機会にexeclp()からexecvp()に変更すること.
4. exsh-2に"^C"のシグナル処理を追加せよ.
子プロセスの実行中に"^C"によって,子プロセスを終了できることを確認せよ.