2017-04-04 26 views
1

我正在創建一個將輸入並給我unix系統輸出的microshell。我正在用||來做這件事而不是|爲一個管道。我的外殼運行良好,如果我給它兩個由||分隔的參數,但如果我只給它一個參數它segfaults。誰能幫我這個?我一直在調試幾個小時,沒有運氣。先謝謝你!C microshell Segfaulting有一個參數,但不是兩個

#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

我猜測了一下,因爲你沒有包括一個輸入和一個輸入的例子。

如果你在你的調試器中看到這個,你會看到如果你只給出一個參數(沒有「||」),index在第二次循環之前調用strstr時將爲NULL。由於strstr不希望有NULL參數,因此會導致崩潰。

+0

謝謝!工作parms的例子就像cat info.txt ||排序,但使用任何命令,但這會打破 – GrapeSoda3

+0

有沒有辦法檢查「||」那會接受一個NULL? – GrapeSoda3

+0

@ GrapeSoda3你在推翻它。 'if(index!= NULL && strstr(index,「||」)!= NULL)'。 – 1201ProgramAlarm