2013-10-08 81 views
-2
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

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

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

typedef struct list 
{ 
    int num; 
    int *ptr; 
    struct history * next; 
}history; 

void setup(char inputBuffer[], char *args[],int *background) 
{ 
    int length, /* Number of characters in the command line */ 
     i,  /* Loop index for 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 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 */ 
} 

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("CSE2431Sh->"); 
     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. */ 

     int child_pid; 
     int status; 
     int ph; 
     history *history = NULL; 

     child_pid = fork(); 

     if(child_pid == 0) 
     { 
       ph++; 
       history->num = ph; 
       history->ptr = args; 
       execvp(args[0],args); 
       /* If execvp returns, it must have failed. */ 

       printf("Execvp Failed\n"); 
       exit(0); 
     } 
     else 
     { 
       if(background == 0) 
       { 
         int parent_pid; 
         while ((parent_pid = wait(&status)) != -1 && parent_$ 
           ; 
       } 
       else 
       { 
         setup(inputBuffer, args, &background); 
       } 
     } 
    } 
} 

我试图将历史功能添加到外壳。 shell应该存储命令并编号。它也应该能够恢复最后的8个命令以再次运行。例如,如果已经由用户28-35输入了35个命令应该能够被恢复。用户应该能够通过键入history来查看最后8个命令,并通过键入x num来运行前一个命令,其中num是命令编号,或者xr运行最近的命令。我的计划是使用一个链表,但我遇到了麻烦,没有几个小时才能完成它。将历史功能添加到外壳

+0

您对这项任务有什么问题?你的问题越具体,你就可以有更好的机会帮助你。 – simonc

+1

“[你]没有几个小时才能完成”?具体编程问题的答案不是时间依赖性的。如果链接列表是正确的答案,那么现在就是这个正确的答案,并且在六个月之后。 –

+1

如果要保存在历史记录中的命令数有固定的数字,可以使用数组。当索引到达数组的末尾时,将其包装到开头。没有列表或指针需要。 Google循环缓冲区。 –

回答

0

正如我们在您的previous post推荐:

怎么样linked list,你还存储长度,第一 和最后一个项目列表?这些项目是来自您的 inputBuffer的命令。

+0

如果您查看已添加的代码,我尝试了链接列表。我无法完成它 – ab91

+0

这不是'链接列表'的完整实现,[这里](http://www.cprogramming.com/tutorial/c/lesson15.html)是一个教程的链接,将帮你。 – HappyDump