2013-06-13 57 views
1

我實際上是想在C中實現一個基本的minishell。爲此,我做了一個解析用戶在控制檯中輸入內容的函數。我解析了它,然後我想使用管道將命令發送到控制檯。我不明白爲什麼我的管道不能正常工作。 我檢查瞭解析,它似乎很好,我有正確的命令參數的功能。 事情是,我的管道代碼字面上什麼都不做,我不明白爲什麼。 這是我的代碼。 預先感謝您。管道在執行minishell時不工作

#define READ 0 
#define WRITE 1 

char *cmds[5] = {0}; 

int main() {  
    char *saisie = (char*)malloc(100*sizeof(char*)); 
    char *saisie2 = (char*)malloc(100*sizeof(char*)); 
    gets(saisie); 
    int ncmds = 0; 
    int k = 0; 

    char* token = (char*)malloc(100*sizeof(char*)); 
    char* tofree; 

    if(*(saisie + 0) == '$'){ 
     if(*(saisie + 2) == 'e' && *(saisie + 3) == 'x' && *(saisie + 4) == 'i' || *(saisie + 5) == 't'){ 
      exit(0); 
     } 
     else{ 
      int i; 
      for(i = 0;i<99;i++){ 
       *(saisie2+i) = *(saisie+i+1); 
      }  
      free(saisie); 

      if (saisie2 != NULL) { 
       tofree = saisie2; 

       while ((token = strsep(&saisie2, "|")) != NULL){ 
        cmds[ncmds] = token; 
        ncmds++; 
       } 
       free(tofree);   
      } 
     } 
    } 

    exe(cmds, ncmds); 
    while(wait(NULL) > 0); 
    return 0; 
} 

int exe(char *cmds[], int ncmds){ 
    int fdin, fdout; 
int fds[2]; 
int i; 
int status; 
fdin = 0; 
for(i=0; i < ncmds-1; i++){ 
    pipe(fds); 
    fdout = fds[WRITE]; 

    if(fork() == 0){ 
     if(fdin != 0) { 
      close(0); 
      dup(fdin); 
      close(fdin); 
     } 
     if(fdout != 1) { 
      close(1); 
      dup(fdout); 
      close(fdout); 
     } 
     close(fds[READ]); 
     const char* prog2[] = {cmds[i], "-l", 0}; 
     execvp(cmds[i], prog2); 
     fprintf(stderr, "si esto se ve es un error\n"); 
     exit(1); 
    } 

    if(fdin != 0) 
     close(fdin); 
    if(fdout != 1) 
     close(fdout); 

    fdin = fds[READ]; 
} 

/* Ultimo comando */ 
fdout = 1; 
if(fork() == 0) { 
    if(fdin != 0) { 
     close(0); 
     dup(fdin); 
     close(fdin); 
    } 
    const char* prog2[] = {cmds[i], "-l", 0}; 
    execvp(cmds[i], prog2); 
    close(fds[READ]); 
    exit(1); 
} 

if(fdout!= 1) 
    close(fdout); 
if(fdin != 0) 
    close(fdin); 

    } 
} 
+0

你應該檢查'fork()的<0'的失敗叉 – leonhart

+2

不要使用'得到()'。對於'$ DEITY'的愛,*絕對不要使用'gets()'*! –

+0

那麼,我使用了一些打印功能來驗證程序在不同的條件下進入並確實如此。這個問題似乎來自與dup的錯誤鏈接,或者關閉... – pdilau

回答

2
int exe(char *cmds[], int ncmds){ 
    int p2c[2];//pipe parent to child 
    int c2p[2];//pipe child to parent 
    int i; 
    int status; 
    int pid; 
    char buf[4096]; 
    memset(buf, 0, 4096); 

    for(i=0; i < ncmds; i++){ 
     pipe(p2c); 
     pipe(c2p); 

     pid = fork(); 
     if(pid < 0) { 
      exit 1; 
     } 
     if(pid == 0){ //in child 
      close(1); 
      dup2(c2p[1],1); // make child write to c2p pipe instead of stdout 
      close(0); 
      dup2(p2c[0],0); // make child read from p2c pipe instead of stdin 
      close(p2c[1]); 
      close(c2p[0]); 
      const char* prog2[] = {cmds[i], "-l", 0}; 
      execvp(cmds[i], prog2); 
      fprintf(stderr, "si esto se ve es un error\n"); 
      exit(1); 
     } 
     //in parent 
     write(p2c[1], buf, strlen(buf)); //write the last output to child 
     close(p2c[1]); 
     close(c2p[1]); 
     memset(buf,0,4096); 
     if(read(c2p[0], buf, 4096) > 0){ //read output from child 
      if(i == ncmds -1){ 
       printf("result:\n"); 
       printf("%s\n", buf); 
      } 
     } 
    } 
} 
+0

我真的不明白父母應該做什麼。我不太瞭解如何向控制檯發送信息。對於那些似乎很簡單的問題,我很抱歉,但我開始於C ... – pdilau

+0

@ user2480503在子進程中,您將1(stdout)的fd作爲管道,所以'execvp( cmds [i],prog2);現在應該在控制檯中顯示的內容會轉到管道(並且不會顯示在控制檯中)。那麼在父進程中,您必須從管道讀取輸出並將其打印到控制檯。 – leonhart

+0

所以我想在父:system(fds [READ])中使用類似的東西。我所理解的是,exec系列的功能是假設執行一個命令,就像我們在控制檯中執行它們一樣。 我確實明白我不讀取父級管道的輸出。我是否應該發送一個旨在將指令發送給控制檯的功能,併發送給控制檯。 我不知道我是否清楚地解釋了我的錯誤... – pdilau