2017-04-04 12 views
1

私は入力を受け取り、UNIXシステムの出力を与えるマイクロシェルの作成に取り組んでいます。私はこれを||ただの代わりに|パイプ用。私のシェルは、||で区切られた2つの引数を与えてもうまく動作しますが、引数を1つだけ与えるとsegfaultsになります。誰もこれで私を助けることができますか?私は運がない時間にデバッグしています。前もって感謝します!CのマイクロシェルSegfaultingの引数は1つではなく2つではありません

#include <iomanip> 
#include <iostream> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <errno.h> 
#include <stdio.h> 

using namespace std; 
int main() 
{ 
    char command[160]; 
    pid_t pid1 = 1, pid2 = 1; 

    cout << "myshell> "; 
    cin.getline(command, 160); 

    while (strcmp(command, "q") != 0 && strcmp(command, "quit") != 0 && pid1 > 0 
      && pid2 > 0) 
    { 
     char* arg1[6]; 
     char* arg2[6]; 
     char path1[21], path2[21]; 
     int pipefd[2]; 
     arg1[0] = NULL; 
     arg2[0] = NULL; 

     getParms(command, arg1, arg2); 

     if (pipe(pipefd) < 0) 
     { 
      perror("Pipe"); 
      exit(-1); 
     } 

     pid1 = fork(); 
     if (pid1 < 0) 
     { 
      perror("Fork"); 
      exit(-1); 
     } 

     if (pid1 == 0) 
     { 

      if (arg2[0] != NULL) 
      { 
       close(pipefd[0]); 
       close(1); 
       dup(pipefd[1]); 
       close(pipefd[1]); 
      } 

      strcpy(path1, "/bin/"); 
      strcat(path1, arg1[0]); 
      if (execvp(path1, arg1) < 0) 
      { 
       strcpy(path1, "/usr/bin/"); 
       strncat(path1, arg1[0], strlen(arg1[0])); 
       if (execvp(path1, arg1) < 0) 
       { 
        cout << "Couldn't execute " << arg1[0] << endl; 
        exit(127); 
       } 
      } 

      if (arg2[0] == NULL) 
      { // Parent process 
       close(pipefd[0]); //read 
       close(pipefd[1]); //write 

       waitpid(pid1, NULL, 0); // Waits for child2 
       cout << "myshell> "; 
       cin.getline(command, 160); 
      } 
     } 

     else if (arg2[0] != NULL) 
     { 
      pid2 = fork(); 
      if (pid2 < 0) 
      { 
       perror("Fork"); 
       exit(-1); 
      } 

      if (pid2 == 0) 
      { 
       close(pipefd[1]); 
       close(0); 

       dup(pipefd[0]); 
       close(pipefd[0]); 

       strcpy(path2, "/bin/"); 
       strncat(path2, arg2[0], strlen(arg2[0])); 
       if (execvp(path2, arg2) < 0) 
       { 
        strcpy(path2, "/usr/bin/"); 
        strncat(path2, arg2[0], strlen(arg2[0])); 
        if (execvp(path2, arg2) < 0) 
        { 
         cout << "Couldn't execute " << arg2[0] << endl; 
         exit(127); 
        } 
       } 
      } 

      else 
      { // Parent process 
       close(pipefd[0]); //read 
       close(pipefd[1]); //write 

       waitpid(pid2, NULL, 0); // Waits for child2 
       cout << "myshell> "; 
       cin.getline(command, 160); 
      } 
     } 
    } 
    return 0; 
} 

void getParms(char str[], char* args[], char* args2[]) 
{ 
    char* index; 
    int i = 0; 
    int j = 0; 

    index = strtok(str, " "); 

    // While the token isn't NULL or pipe 
    while (index != NULL && strstr(index, "||") == NULL) 
    { 
     args[i] = index; 
     index = strtok(NULL, " "); 
     i++; 
    } 
    args[i] = (char*) NULL; // makes last element Null 

    if (strstr(index, "||") != NULL) 
    { 
     index = strtok(NULL, " "); 
     while (index != NULL) 
     { 
      args2[j] = index; 
      index = strtok(NULL, " "); 
      j++; 
     } 
    } 

    args2[j] = (char*) NULL; // makes last element Null 
} 

答えて

1

入力が正しく機能していないか、そうでない入力の例が含まれていないため、少し推測しています。

デバッガでこれを見ると、1つの引数( "||"を付けない)を指定した場合、の呼び出しではindexがNULLになります。 strstrはNULLパラメータを期待しないため、クラッシュが発生します。

+0

ありがとうございました!作業パラームの例は、cat info.txtのようなものになります。ソートしますが、コマンドを使用していますが、これで中断します – GrapeSoda3

+0

"||"をチェックする方法はありますか?それはNULLを受け入れるでしょうか? – GrapeSoda3

+0

@ GrapeSoda3あなたはそれを考え直しています。 'if(index!= NULL && strstr(index、" || ")!= NULL)'です。 – 1201ProgramAlarm

関連する問題