2017-04-05 95 views
0

我想在C++中編寫一個microshell,它將採用1或2個參數並在UNIX中運行它們。我的shell有兩個由||分割的參數很好,但是當我只運行一個時,我得到一個巨大的分叉錯誤。我的shell會查找||作爲管道而不是|。先謝謝你!當一個arg運行shell時資源暫時不可用

一些功能命令:

貓文件名||分類

ls -l ||少

代碼:

#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; 

void getParms (char[], char* [], char* []); 

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); 
    } 

//cerr <<"This is arg2"<<arg2[0]<<endl; 
    pid1 = fork(); 
    if (pid1 < 0) 
    { 
     perror ("Fork"); 
     exit (-1); 
    } 

    if (pid1 == 0) 
    { 
//cout<<"Child 1"<<endl; 
//cerr<<arg1[0]<<endl; 

     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) 
    { 
//cerr<<"Child 2"<<endl; 
     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 
//cerr<<"in last 2 else"<<endl; 
     close (pipefd[0]); //read 
     close (pipefd[1]); //write 

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


/**************************************************************** 
    FUNCTION: void getParms (char [], char* [], char* []) 

    ARGUMENTS: char str[] which holds full command 
       char* args[] args2[] which will hold the individual commands 

    RETURNS: N/A 

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

    index = strtok(str, " "); 
//cerr<<"before first while"<<endl; 

    // 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 

//cerr<<" getParms before ||"<<endl; 
    if(index != NULL && strcmp(index,"||") != 0) 
    { 
//cerr<<"after checking for ||"<<endl; 
     index = strtok(NULL," "); 
     while (index != NULL) 
     { 
     args2[j] = index; 
     index = strtok(NULL," "); 
     j++; 
     } 
    } 
//cerr<<"After second IF"<<endl; 
    args2[j] = (char*) NULL; // makes last element Null 
} 

回答

0

您的問題是主要的while循環是不會任何在你有另一個命令提示符if-else陳述 - 被一遍又一遍執行相同的語句。當您使用雙管道時,它會轉到else if(arg2[0] != NULL),父進程會顯示新的提示。

嘗試的命令,從主while循環在你if-else聲明同時去除提示和移動提示環路這樣的開頭:

//Move these two below into the while loop 
//cout << "myshell> "; 
//cin.getline(command, 160); 

while (strcmp(command, "q") != 0 && strcmp(command, "quit") != 0 && pid1 > 0 && pid2 > 0) 
{ 
    cout << "myshell> "; 
    cin.getline(command, 160); 
    //... 
} 

儘量不要犯同樣的這些多餘的通話事情。如果你有幾個這樣的東西,你需要改變它可能會變得混亂。

相關問題