アプリ版:「スタンプのみでお礼する」機能のリリースについて

大学で以下のような課題を出されました。

・コマンドライン入力を受け付けて、実行可能ファイルを実行できる
コマンドサーチパスを持っている方が望ましいが、実行時に full path指定
するのでも構わない
・バックグラウンド実行
・標準入出力・エラー出力のリダイレクション
・パイプによる標準入出力の他プロセスへの接続

作成の上で条件は以下の通りです。

・使ってよいのは基本的にはシステムコールのみ
man で (2)
execve, fork, pipe, dup, read, write, open
・プログラム作成の効率化を考慮して以下の library関数は使うことを認める
exec周り execv
文字列関係 str...
入出力関係 fprintf, fgets
入出力関係は、コマンドライン入力、エラー出力に限る

今までshellを作成したことが無くどうすればよいか良く分かりません。
fork()やexec()の意味はなんとなくは理解したのですが・・・

A 回答 (4件)

★まずはコマンドラインの入力処理を作成しましょう。


・簡単なアルゴリズム
 (1)fgets() 関数で文字列を入力待ち状態にします。
 (2)文字列が入力されたら、起動コマンド名とその引数に分割します。
 (3)起動コマンド名にパスがなければ、環境変数 PATH などを参照してパスを探す。
 (4)起動コマンド名が見つからなければエラー表示します。
 (5)起動コマンド名が見つかれば、fork()、exec() で実行します。→バックグラウンドで実行させる。
 (6)(1)へ戻り入力待ち状態を繰り返す。
 上記の方法で簡単なコマンドライン・システムが組めます。
・リダイレクションは標準入出力を dup() 関数などで切り替えます。つまり、
 入力リダイレクションでは標準入力をファイルから読み込むように stdin の属性を変更し、
 出力リダイレクションでは標準出力をファイルに書き込むように stdout の属性を変更します。
・パイプ処理は標準出力を一時ファイルに出力するように加工します。出力リダイレクションの考えと
 同じです。そして、一時ファイルに出力したファイルを標準入力に読み込むように加工します。
 これは入力リダイレクションと同じ考えです。
 このような仕組みの為、先に入出力リダイレクションの機能を作ります。
 上手く実装できたらば、パイプ処理も意外に簡単に作れますよ。

サンプル:
char buff[ 256 ];
char *argv[ 256 ];
int argc;

while ( fgets(buff,sizeof(buff),stdin) != NULL ){ ←(1)入力待ち
 argc = split( argv, buff ); ←(2)コマンド名と引数を分離
 
 if ( (argv[0] = check(argv[0])) == NULL ){ ←(3)コマンド名の有無をチェック
  printf( "エラー表示\n" ); ←(4)コマンド名が見つからないエラー
 }
 else{
  execute( argv[0], argv + 1, argc - 1 ); ←(5)バックグラウンドで実行させる
 }
 free( argv[0] ); ←解放
}

解説:
・split() 関数は文字列 buff をコマンド名と引数に分離して argv のポインタ配列にセットします。
 また、分離した個数をリターンします。分離するときはスペースで分離していきます。
・check() 関数ではコマンド名のパスをチェックしてない場合は環境変数 PATH などを参照して
 パス名を探します。そして、見つかったらばパスを補充した文字列を malloc してリターンします。
 なお、パスを補充しない文字列も malloc してからリターンします。
 コマンド名が見つからない場合は NULL を返すようにします。
・execute() 関数の引数は、コマンド名、引数のポインタ配列、引数の個数です。
 fork()、exec() 関数でプログラムをバックグラウンドで実行するようさせます。
・上記のサンプルには入出力リダイレクションの機能は記述されていません。
 リダイレクションを実装するには <や>の語句を元に標準入出力をファイルに切り替える処理を
 追加します。標準入出力は dup() 関数などを使います。この関数は標準入出力を切り替えるのに
 とても重要な働きがあります。マニュアルなどをよく読み標準入出力を切り替えて下さい。
 標準入出力の切り替えが出来たらば、execute() 関数を実行すれば良い。
・パイプ処理は入出力リダイレクションが出来れば、|文字の前の文字列で1つ実行したら、
 その標準出力を出力リダイレクションと同じ考えて一時ファイルに出力します。
 その後、一時ファイルを入力リダイレクションと同じ考えて stdin に切り替えます。
・以上。参考に。
    • good
    • 0
この回答へのお礼

詳しい回答ありがとうございます
頑張ってみます!

お礼日時:2007/05/09 20:31

なかなかの難問を出題されていますね。


参考文献として、絶版だと思いますが以下のものがあります。

・MS‐DOS用Shellの実現―Unix流シェルのプログラムと使い方 (単行本)
 アレン ホルブ (著), 横山 和由 (翻訳)

amazonのマーケットプレイスにて購入可能です。私はこの本を参考に、まともなshellの無いOSにshellを導入しました。

それから、ちょっと反則技っぽいですが、linux上のc-shellやt-cshellのソースを参考にされるといいと思います。たったこれだけの機能を実現するのが、こんなに大変なの?っていう気分になります。
    • good
    • 0

参考までに、私は参考の書籍を紹介したいと思います。



「UNIX Cプログラミング」という本です。
発行されてから結構経ちますが、この本はUNIXでシステムコールを扱う際に参考になります。
シェルやリダイレクト、パイプ処理なども掲載されています。

図書館などで軽く読んでみても、いいかもしれません。


課題頑張ってくださいね^^

参考URL:http://www.ascii.co.jp/books/books/detail/4-7561 …
    • good
    • 0
この回答へのお礼

回答ありがとうございます
今日学校の図書館で捜して見ます!

お礼日時:2007/05/10 11:02

自分なら


1.入力を受け取り, バラして表示する
2.fork & exec して「コマンドの実行」ができるようにする
3.入出力のリダイレクト
4.パイプ
くらいの順に作っていくかなぁ?
    • good
    • 0
この回答へのお礼

回答ありがとうございます
どういう風にプログラムを組んでいいかもイマイチわからなくて・・・

参考サイトなどがあれば教えていただけないでしょうか?

お礼日時:2007/05/09 19:19

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!