CSHでBG実行するプログラム
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 853
C言語でのシェル作成(csh)で、コマンドの最後に&をつけたときは引数とせずにコマンドをバックグラウンド実行(BG)させるプログラムを作成しています。
BGプロセスが終了した時には終了ステータスを取得し、プロンプトを表示する前に毎回のループで終了した子プロセスの有無をチェックしたいです。
そこで終了ステータスをどのように受けとればいいのか、終了ステータスの確認をどこで行えばいいか分かりません。お教えいただきますと幸いです。
ソースコード
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_ARGS 50
#define MAX 500
int main(void)
{
int argc;
int n = 0;
char input[MAX], *argv[MAX_ARGS], *cp;
char and = '&';
char *bg; //文字列に&がなければNULL
int ret_code1;
pid_t pid;
pid_t pid2;
int pc=0; //プロセスカウンタ
while (1) {
//プロンプトの表示、コマンドの読み込み
n++;
printf("$ ");
fgets(input, sizeof(input), stdin);
printf("%s\n",input);
printf("%d process is running.\n", pc);
if( ret_code1 == 0 ){
printf("SUCCESS! : pid1 = %d\n", pid1);
}
//and='&'を含んでいたらbg!=NULLにしてBG実行であることを明示
bg = strchr(input, and);
if( bg != NULL ) printf("==Run Background==\n");
//コマンドを、'\n'や' 'で分割し,配列argvに格納
//NULLと&がきたら格納終了。これらは配列に入れない
cp = input;
for( argc = 0; argc < MAX_ARGS; argc++ ){
if ((argv[argc] = strtok(cp," &\t\n")) == NULL)
break;
cp = NULL;
}
//分割用の配列を用意
char *str1[MAX_ARGS], *str2[MAX_ARGS];
int comm=0, i=0, j=0;
//入力されたコマンドをstr1,str2に分割する
while (argv[i]) {
if (comm == 0) {
if (*argv[i] == '\0') {
comm = 1;
} else {
str1[i] = argv[i];
str1[i+1] = NULL;
}
} else {
str2[j] = argv[i];
str2[j+1] = NULL;
j++;
}
i++;
}
//内部コマンドの処理(quit,exitなら終了する)
if( strcmp(input,"exit") == 0 || strcmp(input,"quit") == 0){
printf("Good-Bye!\n");
exit(0);
//inputは場所を指すのでstrcmpで1文字ずつ比較している。0の時は等しい。
}
int status;
pid = fork();
//fork()は呼び出し元プロセスを複製して新しいプロセスを生成する
//成功した場合、親プロセスには子プロセスのPIDが返され、子プロセスには0が返される(エラーは-1)
if (pid < 0) {
perror("fork");
exit(-1);
} else if (pid == 0 && comm == 0) {
//子1プロセス時に実行
//printf("You are in child. p=%d\n", pid);
execvp (str1[0], str1);
exit(-1);
} else if (pid == 0 && comm == 1) {
//'\0'を含んでおり子1プロセス時に実行
//printf("You are in child. p=%d\n", pid);
execvp (str1[0], str1);
exit(-1);
} else if (comm == 1){
//子プロセス1の終了を待つ
//waitpid( pid, &status, 0);
pid2 = fork();
if (pid2 == 0) {
//子2プロセス時に実行
execvp (str2[0], str2);
exit(-1);
}
} else if (comm == -1){
//エラー(-1)を返したら警告
printf("An error occurs.\n");
exit(-1);
}
//親プロセス(bg==NULLのとき(&なし)子プロセス終了待機)
if( pid>0 ){
if( bg == NULL ){
waitpid( pid, &status, 0);
}
if( bg != NULL ){
waitpid( pid2, &status, 0);
pc++;
}
}
}
exit(EXIT_SUCCESS);
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
sigaction()等で、SIGCHLDシグナルを受信するようにします。そして、そのシグナルハンドラ内で、waitpid()で子プロセスのステータスを取得します。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 89.97%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
t_obara
2017/11/27 13:43
ご提示されたソースコードだと、どのような点で期待通りに動作しないのかも提示されると、回答が受けられやすいのではないでしょうか。