2013-12-08 56 views
3

我正在linux上創建一個使用各種命令的shell。 我有不同的內置命令,其中一個是「歷史」。 我有一個reshist()函數來重置包含用戶輸入的輸入數組。 我還希望使用execvp()啓用系統命令,並且還需要多個管道操作。execvp:錯誤的地址錯誤

reshist()函數和多個管道操作在不在一起時效果很好,但是當我使用它們時,它會導致execvp()引發「錯誤的地址」錯誤。

我知道reshist()函數不能正確地將輸入添加到列表中,但這不是什麼大不了的事。 問題是爲什麼我得到錯誤。

可能是什麼原因?任何更好的想法,使他們一起工作?

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdbool.h> 
#include <sys/types.h> 
#include <signal.h> 
#include <errno.h> 

#define MAX_BUFFER 129      // max line buffer 
#define MAX_ARGS 32       // max # args 
#define SEPARATORS " \t\n"      // token sparators 
char *args[MAX_ARGS]; 

int print[16]; 
int get[16]; 
int fd[2]; 

char histarr[10][129]; // History array 
char histel[129]; 

void reshist(void) 
{ 
    //HISTORY RESORTING 

    int counter = 0; 
    while (counter < 10) 
    { //shifting all elements by one from the last element of the list 
    if (histarr[counter] == NULL) 
    { 
     strcpy(histarr[counter], histel); //first element of the history will contain the last command 
     break; 
    } 
    counter++; 
    } 
    if (counter == 10) 
    { 
    counter = 1; 
    while (counter < 10) 
    { 
     strcpy(histarr[counter - 1], histarr[counter]); 
     counter++; 
    } 
    strcpy(histarr[9], histel); 
    } 

    memset(histel, 0, 127); 
    //HISTORY RESORT ENDS 
} 

void setup(void) 
{ 

    char buf[MAX_BUFFER];      // line buffer 
    //char * args[MAX_ARGS];      // pointers to arg strings 
    char ** arg;        // working pointer thru args 
    char * prompt = "333.sh>";     // shell prompt 

    /* keep reading input until "quit" command or eof of redirected input */ 

    while (!feof(stdin)) 
    { 

    /* get command line from input */ 
    fputs(prompt, stdout);    // write prompt 
    if (fgets(buf, MAX_BUFFER, stdin)) 
    { // read a line 

     /* tokenize the input into args array */ 

     arg = args; 
     *arg++ = strtok(buf, SEPARATORS); // tokenize input 
     while ((*arg++ = strtok(NULL, SEPARATORS))) 
     ; 
     // last entry will be NULL 

     strcpy(histel, buf); 
     reshist(); 

     pid_t pid; 
     int print[16]; 
     int get[16]; 
     int fd[2]; 

     int count = 0; 
     int i = 0; 
     while (args[i] != NULL) 
     { 
     if (0 == strcmp(args[i], "|")) 
     { 
      count++; 
     } 
     i++; 
     } 

     char *arrays[count + 1][i - count]; // array lines bordered as arrays[numberOfPipes+1][numberofArguments-numberOfPipes] 

     i = 0; 
     int x = 0; 
     int y = 0; 
     while (args[i] != NULL) 
     { 
     if (strcmp(args[i], "|") != 0) 
     { 
      arrays[x][y] = args[i]; //builting arrays that is going to be sent to the each process, each row of the matrix is an array to be sent to another process 
      y++; 
     } 
     else 
     { 
      x++; 
      y = 0; 
     } 
     i++; 
     } 

     int h = 0; 
     int a = 0; 
     int k = 0; 
     for (k = 0; k <= count; k++) 
     { 

     get[k] = -1; 
     print[k] = -1; 
     } 
     //create required number of pipes 
     for (a = 0; a < count; a++) 
     { 
     if (pipe(fd) == -1) 
     { 
      perror("Pipe failure"); 
      continue; 
     } 
     get[a + 1] = fd[0]; 
     print[a] = fd[1]; 
     } 

     for (k = 0; k <= count; k++) 
     { 

     pid = fork(); 

     if (pid < 0) 
     { 
      printf("fork failed\n"); 
     } 
     else if (pid == 0) 
     { 
      if (print[k] != -1) 
      { 

      if (dup2(print[k], 1) == -1) 
      { 
       perror("dup2 error"); 
       exit(1); 
      } 
      } 

      if (get[k] != -1) 
      { 

      if (dup2(get[k], 0) == -1) 
      { 
       perror("dup2read error"); 
       exit(1); 
      } 
      } 

      for (h = 0; h <= count; h++) 
      { 
      close(print[h]); 
      close(get[h]); 
      } 

      if (execvp((const char*) arrays[k][0], arrays[k]) < 1) 
      { 
      perror("error"); 
      exit(1); 
      } 

      exit(0); 
     } 
     else 
     { 
      int stat; 
      close(print[k]); 
      close(get[k]); 
      waitpid(pid, &stat, 0); 

     } 

     } 

    } // system command else ends   

    } 
} 

int main(void) 
{ 
    setup(); 
    /** 
    * After reading user input, the steps are: 
    * (1) fork a child process using fork() 
    * (2) the child process will invoke execvp() 
    * (3) if command included &, parent will invoke wait() 
    */ 
    return 0; 
} 
+0

什麼錯誤?你可以在你的問題中包括這個嗎? –

+2

請注意,當'strtok()'切碎了時,'strcpy(histel,buf)'調用只會將第一個字複製到'histel'中。這就是爲什麼有些人(比如我)不喜歡或者使用'strtok()'的原因之一。 –

+1

有效的'while((* arg ++ = strtok(NULL,SEPARATORS))) ;'循環什麼都不做,除了遞增arg幾次並指向緩衝區。在循環之後,緩衝區將恢復到其原始狀態,並且指針將指向子串,全部直到行結束。 (確實:strtok()很糟糕) – wildplasser

回答

9

代碼似乎錯過NULL -terminate arrays[k]。使arrays[k]中的最後一項進行NULL


更新

if (execvp((const char*) arrays[k][0], arrays[k]) < 1) 

應該

if (execvp(arrays[k][0], arrays[k]) == -1) 
的更加直截了當只是

execvp(arrays[k][0], arrays[k]); 
    perror("execvp() failed"); 

作爲exec*()的成員 - 功能家族僅在錯誤上返回