2017-10-11 7 views
0

コマンドを読み込んで順番に実行するシンプルなシェルを作成する必要があります。条件が主関数の形式を変更しておらず、実行関数が再帰的でなければなりません。 主な問題は、waitpidが動作しないようです。しかし私は知っている、私のコードで非常に多くの問題があります。私がどこから出発すべきか教えてください。シンプルシェルin c:waitpidシステムコールが動作しない

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#define MAX 10 

char cmmd[MAX][256]; 
int sp; 
char *argv[10]; 
int size; 

void ClearLineFromReadBuffer(void){ 
    while(getchar() != '\n'); 
} 
void printCommands(){ 
    size = sp+1; 
    //print by moving stack pointer 
    while(1){ 
     if (sp==-1) break; 
     printf("Command line : %s\n", cmmd[sp]); 
     sp--; 
    } 
    printf("print end\n"); 
} 



void readCommandLines(){ 
    int a = 0; //return of scanf 
    while (1){ //write commends to cmmd untill get ctrl+d 
     printf(">"); 
     a = (scanf("%[^\n]s", cmmd[sp])); //take input to str untill get enter(scanf returns -1) 
     if (a==-1) {sp--; break;} 
     if (a==1) ClearLineFromReadBuffer(); 
     if (a==0) {printf("error"); break;} 
     sp++; 
    } 
    printf("\n"); 
} 

void readACommand(char *line){ //line takes string's name. 
    int i=0; 

    argv[i]=strtok(line," "); //i==0 
    while(strtok(line," ")!=NULL){ 
     i++; 
     argv[i]=strtok(NULL," "); 
    } 
    printf("%s",argv[0]); 
    printf("%s",argv[1]); 
} 

void executeCommands(){ //Recursive function 
    int n = sp; 
    n++; 
    printf("%d",n); 
    printf("%s",cmmd[n]); 
    char *cmd_line = cmmd[n]; //command line which child process will execute 

    unsigned int child_pid; //fork() returns process id of child in parents process 
    int status; //status takes return of child's exit() 
    child_pid=fork(); 
    if (child_pid != 0){ // Parents process 
     printf("parents access"); 
     waitpid(child_pid,&status,0); 
     printf("***Process %d Child process %d DONE with status %x\n\n",getpid(),child_pid,status); 

     sp++; 
     if(sp<size) 
      executeCommands(); 
    } 
    else if (child_pid == 0){ //fork() returns 0 in child process 
     printf("***Process %d Executing Command %s",getpid(),cmd_line); 
     readACommand(cmmd[n]); 
     execve(argv[0],argv,NULL); 
     printf("ERROR - not executing command \"%s\"\n",argv[0]); //can be printed because exec() failed 
    } 
} 

int main(){ 
    readCommandLines(); 
    printCommands(); 
    executeCommands(); 
    return(0); 
} 

これは結果です。 enter image description here

+1

おそらく関連性があります:あなたの引数リストを 'NULL 'で終了する必要があります。 –

+1

あなたのトークン化ループは非常に疑わしいです。私は2つ以上の議論があれば無限になると思う。そしてそれはNULLで終了しません。 –

+0

Thanlあなた。私は固定し、それを分離するのに成功しますが、ループは決して終了しません。あなたは何が問題なのか教えてくれますか?各argvを印刷しようとすると、最後の引数に印刷できますが、whileループにとどまります。 –

答えて

1

文字列をトークン化する方法は非常に間違っています。そこstrtok呼び出しの多くはだ、とあなたは初期化文字列ではなく、NULL

でループでstrtokを呼び出しているプラ​​スあなたがある最後の引数、後NULLに設定していないので、あなたのループが無限ループすることができでNULLポインタを検出する実行

#include <stdio.h> 
#include <string.h> 

char *argv[100]; 

void readACommand(char *line){ //line takes string's name. 
    int i=0; 

    argv[i]=strtok(line," "); //i==0 
    while(argv[i]!=NULL){ 
     argv[++i]=strtok(NULL," "); 
    } 
} 

int main() 
{ 
    char line[] = "this is a command"; 
    char **ptr=argv; 

    readACommand(line); 
    while(*ptr != NULL) 
    { 
     printf("Arg: %s\n",*ptr); 
     ptr++; 
    } 
    return 0; 
} 

(:(なしサイズが渡されない)

ここでは、スタンドアロンの例だと、日常の適切readACommand引数が不足していたときに知っておくexecvで必要とされますend):

Arg: this 
Arg: is 
Arg: a 
Arg: command 
関連する問題