
簡単んなシェルプログラミングを組んでいます。
そこである問題にぶつかっています。
********************************************
int main()
{
int argc, n = 0;
pid_t pid;
int status;
char input[MAX_LEN], *argv[MAX_ARGS];
char path[30];
while (1) {
/* プロンプトの表示 */
++n;
printf("command[%d] ", n);
fgets(input, MAX_LEN, stdin);
/*
改行を除去し、 空白,タブ区切りでコマンド列に分割、argvに単語毎に格納
(処理は略)
*/
sprintf(path,"%s",argv[0]);//PATH取得
pid = fork();
/*#### 子プロセス ####*/
if(pid == 0){
execvp(path,argv);
exit(0);
}
/*#### 親プロセス処理 ####*/
} else {
wait(&status);
}
}//while
}//main
としています。
ここで
ls
ps
rm
mkdir
emacs
などのコマンドは普通につかえるのですが、
cd ..
や、
mkdir test
cd test
としてもそのディレクトリへ移動することができません。どうすればいいでしょうか?このプログラムをうごかしたままディレクトリを移動することは可能でしょうか?
No.5ベストアンサー
- 回答日時:
おおよそ、他の方が書かれてますが、カレントディレクトリはプロセス固有の値で親から子へは継承されますが、子プロセス内で変更しても親へは伝わりません。
対応としては、コマンドがcdであることをチェックして、その場合は、fork&exec でなく、自分のプロセス内でchdirというシステムコールでカレントディレクトリを変更します。
環境変数PWDの話が出ていますが、カレントディレクトリと環境変数PWDには直接の関係がありません。PWDも変更したいならさらにsetenvサブルーチンで変更します。
話は変わって、
>execvp(path,argv);
>exit(0);
となっていますが、execvpの次の文が実行されるのはexecvpが失敗した時(pathで指定したファイルが無い等)なので、エラーメッセージを出したほうが良いでしょう。最初にそうしていれば、cd を入力するとエラーになる(cdはシェル組み込みコマンドで、cdというファイルは無いため)ので気づいたかも。
つまり、実は cd test と入れたときには子プロセスでtestにカレントディレクトリが移って親に反映しなかったわけではなく、execvpが失敗してexit(0)で子プロセスが終了していたと思われます。いずれにせよ対応は上に書いた通りでOKです。
シェルには多くの組み込みコマンドがあるので、それらのどこまで組み込むかが考えどころですね。cd のように組み込み処理が必須のコマンドもあれば、echo や test のようにコマンドファイルとしても存在するのに速度向上のために組み込みコマンドになっているものと二通りあります。
No.6
- 回答日時:
何か結局私が混乱させていたようですので役に立つか分かりませんがcdの引数無しでホームに移る部分書いておきます。
お騒がせしました。
if(argv[1] == NULL){
if(chdir(getenv("HOME")) <0)
perror("cd");
}
else{
if(chdir(argv[1]) <0)
perror("cd");
}
No.4
- 回答日時:
なんか私はいろいろ勘違いしていたようですね。
どうやら断食中で頭がぼーっとしているようです。
環境変数PWDの問題じゃないんですがカレント作業ディレクトリは継承されています。
どのように継承されてるかはちょっと私には分かりませんが・・・。
cdってshに組み込まれてるんですよねたしか。
だから扱いが難しそうですね。
難しそうですがUNIXのシェルのソースを見てみるのも手だと思います。
No.3
- 回答日時:
ummuさんの言われている通り、コマンドcdに関しては、子プロセスにforkして実行するのではなく、カレントプロセス内で実行する必要があります。
子プロセスでcdしても、親プロセス(=shellとして機能している方)には影響しないので。
which cdの結果を見ると、分かるかも。
No.1
- 回答日時:
前の質問で全然回答になっていなくて混乱させてしまったものと思われます。
すいません。同じもの書いてみましたが引数をとれると思います。
argvへの格納がおかしいのでは?
cdに関してですが毎回新たに子プロセスを生じているため子プロセスは親プロセスの環境変数PWDを継承しています。
このプログラムでは別にforkする必要が無いように思えます。
この回答への補足
再びご回答ありがとうございます
>>argvへの格納がおかしいのでは?
argvの中身を確認したところ、 cd testとしたところ、
argv[0]=cd,
argv[1]=test
と格納されていましたので、ここは大丈夫だと思います。
>>cdに関してですが毎回新たに子プロセスを生じているため子プロセスは親プロセスの環境変数PWDを継承しています。このプログラムでは別にforkする必要が無いように思えます
はじめ親プロセスにexecvpを記述したところ、プログラム起動後、一回のコマンドでプログラムが終了してしまいました。なので子プロセスを生成しないと、exec系でこのプログラムが終わってしまうようなんです。まだforkを使い始めたばかりで知識があまりないのですが。以下のように把握してよろしいでしょうか。
このプログラムだとcdのコマンドは子プロセスで実行する事になる。その後に行うコマンドは、親プロセスから継承した環境変数をもつ新たに生成された子プロセスだから、また同じフォルダにいることになる。
もしそうであれば何か解消方法はあるでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VB.NETで起動したExcelの閉じ方...
-
C#でのbatファイル実行結果取得
-
バックグラウンドのプロセスの...
-
ADOでアクセスのレコードに...
-
Process.Startの戻り値を後で取得
-
タスクマネージャーのプロセス...
-
OSPFでプロセスを分ける意義に...
-
IISがフリーズ
-
プロセスのアタッチ・デタッチ...
-
vb.netでEXCEL起動がうまくでき...
-
VB6.0 SHELLで起動...
-
Visual C++からpingを実行して...
-
SendMessageが失敗するときがある
-
VBS(WSH)で開いたIEのウィンド...
-
シェルで親プロセス終了時に子...
-
EXE間でデータを受け渡し時のka...
-
UNIX関数?(popen)...
-
デスクトップ上のアイコン名の...
-
フレームワークとプロセスの違...
-
怪しいプロセス教えてください。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
プロセスのアタッチ・デタッチ...
-
非表示になったエクセルは?
-
C#でのbatファイル実行結果取得
-
Process.Startの戻り値を後で取得
-
タスクマネージャーのプロセス...
-
SendMessageが失敗するときがある
-
VB6.0 SHELLで起動...
-
Linuxでのスレッド間メッセージ...
-
vb.netでEXCEL起動がうまくでき...
-
explorer.exeが異様にメモリを食う
-
プロセスIDの取得方法について
-
IISがフリーズ
-
jdbcのプロセスの処理について
-
c言語でプロセスIDを調べたい
-
セマフォとmutexの違いは?
-
警告『 別のプロセスで使用され...
-
ADOでアクセスのレコードに...
-
OSPFでプロセスを分ける意義に...
-
Windowsでのfork方法
おすすめ情報