2012-05-31 62 views
0

我試圖爲簡單的shell實現歷史記錄功能。歷史應該保存最後執行的10個命令。我將代碼放在下面,但是我遇到了一些問題。在簡單的UNIX Shell中實現歷史記錄的問題

首先,當我輸入一個(或兩個)命令並輸入history來顯示歷史記錄時,不顯示任何內容。但是,當我輸入更多的命令時,將顯示整個歷史記錄(像它應該那樣),但是每個歷史索引旁會顯示一串零。

我在做什麼錯,我該如何解決這個問題?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */ 

char *history[10][MAX_LINE]; 
int placePointer; 


/** 
* setup() reads in the next command line, separating it into distinct tokens 
* using whitespace as delimiters. setup() sets the args parameter as a 
* null-terminated string. 
*/ 

void setup(char inputBuffer[], char *args[],int *background) 
{ 
    int length, /* # of characters in the command line */ 
     i,  /* loop index for accessing inputBuffer array */ 
     start, /* index where beginning of next command parameter is */ 
     ct;  /* index of where to place the next parameter into args[] */ 

    ct = 0; 

    /* read what the user enters on the command line */ 
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE); 

    start = -1; 
    if (length == 0) 
     exit(0);   /* ^d was entered, end of user command stream */ 
    if (length < 0){ 
     perror("error reading the command"); 
     exit(-1);   /* terminate with error code of -1 */ 
    } 

    /* examine every character in the inputBuffer */ 
    for (i = 0; i < length; i++) { 
     switch (inputBuffer[i]){ 
     case ' ': 
     case '\t' :    /* argument separators */ 
      if(start != -1){ 
       args[ct] = &inputBuffer[start]; /* set up pointer */ 
       ct++; 
      } 
      inputBuffer[i] = '\0'; /* add a null char; make a C string */ 
      start = -1; 
      break; 

     case '\n':     /* should be the final char examined */ 
      if (start != -1){ 
       args[ct] = &inputBuffer[start];  
       ct++; 
      } 
      inputBuffer[i] = '\0'; 
      args[ct] = NULL; /* no more arguments to this command */ 
      break; 

     case '&': 
      *background = 1; 
      inputBuffer[i] = '\0'; 
      break; 

     default :    /* some other character */ 
      if (start == -1) 
       start = i; 
     } 
    }  
    args[ct] = NULL; /* just in case the input line was > 80 */ 
} 

void displayHistory(){ 
    printf("Display History:\n"); 
    int i = placePointer; 
    int j; 
    int counter; 
    while(counter < 10) { 
     printf("%d: ",counter); 
     for (j = 0; j < MAX_LINE; j++) { 
      printf("%d",history[i][j]); 
     } 
     printf("\n"); 
     i = (i + 1) % 10; 
     counter++; 
    } 
} 
/* 
void runHistoryAt(int index){ 
    printf("Run History At:\n"); 
    char *arg1 = &history[placePointer + index][0]; 
    char *argLine[MAX_LINE/2+1]; 
    int j; 
    for (j = 0; j < MAX_LINE/2+1; j++) { 
     *argLine[j] = history[placePointer + index][j]; 
    } 
    execvp(arg1,argLine); 
}*/ 

int main(void) 
{ 
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */ 
    int background;    /* equals 1 if a command is followed by '&' */ 
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */ 


    while (1){   /* Program terminates normally inside setup */ 
     background = 0; 
     printf("COMMAND->"); 
      fflush(0); 
      setup(inputBuffer, args, &background);  /* get next command */ 

     /* the steps are: 
     (1) fork a child process using fork() 
     (2) the child process will invoke execvp() 
     (3) if background == 0, the parent will wait, 
      otherwise returns to the setup() function. */ 

     pid_t pid = fork(); 
     printf("Fork created.\n"); 


     if(pid < 0){ 
      printf("Fork failed.\n"); 
     }else if(pid == 0){ 
      if(strcmp(args[0],"history") == 0){ /* Print History */ 
       displayHistory(); 
      }else if(strcmp(args[0],"r") == 0){ /* r num */ 
       int index = (int) args[1]; 
       /*runHistoryAt(index - 1);*/ 
      }else if(strcmp(args[0],"rr") == 0){ /* Run recent */ 
       /*runHistoryAt(0);*/ 
      }else{ /* Execute normally */ 
       printf("executing..., adding to history buffer\n"); 
       /* Add args to history buffer */ 
       int j; 
       for (j = 0; j < sizeof(args); j++) { 
        history[placePointer][j] = args[j]; 
       } 
       placePointer = (placePointer + 1) % 10; 
       /* Execute! */ 
       execvp(args[0],args); 
      } 
     } 

     if(background == 0){ 
      wait(NULL); 
     }else{ 
      setup(inputBuffer, args, &background); 
     } 
    } 
} 
+0

說真的,你最好自己調試一下。要求陌生人通過檢查發現代碼中的錯誤並不富有成效。 –

回答

1

args指針全部是指針到您的inputBuffer,其中包含了最新的輸入線輸入。因此,當您將args保存到history時,您只是保存指針,而不是實際指向的字符串,它們仍然(僅)在inputBuffer中。當你讀取下一個命令時,它會覆蓋inputBuffer使得所有保存的指針無效 - 它們現在指向當前命令的一部分,而不是舊命令。

+0

那麼,解決這個問題的一個辦法是,我應該保存歷史中的值,而不是指針?我該怎麼做? – user906153

+0

@ user906153,嘿,你有沒有機會得到這個工作代碼或找出並記住爲什麼你的代碼不工作? – wolfclique

相關問題