2010-11-20 55 views
2

我正在编写简单c壳体的代码。它存储最后10条命令的历史记录。如果输入'r'作为命令,那么它应该从历史记录运行最近的命令。此外,如果输入'r x',其中'x'是要从历史记录执行的命令的第一个字母,那么它将运行以该字母开头的最新命令。简单壳体中的段错误

我遇到了从历史记录复制到inputBuffer的问题;当我尝试去做时会出现分段错误。

这里是代码(这是凌乱的我一直在尝试很多不同的事情,希望修复它)。 任何意见将不胜感激!

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <string.h> 


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

#define buffer "Command History:\n" 

char history[10][MAX_LINE]; 
int count = 0; 
int caught = 0; 
int ct =0; 
int rFlag =0; 

/** 
* 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 shell(void); 

void printHistory() 
{ 
     int i; 
    int j = 0; 
    int hcount = count; 

     for (i = 0; i<10;i++) 
    { 
     printf("%d. ", hcount); 
     while (history[i][j] != '\n' && history[i][j] != '\0'){ 
     printf("%c", history[i][j]); 
     j++; 
    } 
    printf("\n"); 
    j = 0; 

    hcount--; 
    if (hcount == 0) 
    break; 
    } 


} 

/* the signal handler function */ 
void handle_SIGINT() 
{ 
    write(STDOUT_FILENO,buffer,sizeof(buffer)); 
    printHistory(); 
    printf("\nCOMMAND->"); 
    caught = 1; 
} 


void setup(char inputBuffer[], char *args[],int *background) 
{ 
    int k; 
    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; 

    printf("Setup"); 

    /* read what the user enters on the command line */ 
    if (rFlag!=1) 
    { 
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE); 
    rFlag = 0; 
    } 
    printf("buff=%i", strlen(inputBuffer)); 
    if (caught == 1) 
{ 
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE); 
    caught = 0; 
} 

    if ((strcmp(inputBuffer,"r\n\0")!=0) && (strncmp(inputBuffer, "r x", 2)!=0)) 
    { 
     for (i = 9;i>0; i--) 
    { 
     strcpy(history[i], history[i-1]); 
    } 
     strcpy(history[0],inputBuffer); //this works 
     count++; 
    } 


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


    /* examine every character in the inputBuffer */ 

     printf("beforeCase"); 
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; 

    default :    /* some other character */ 
    if (start == -1) 
     start = i; 
    if (inputBuffer[i] == '&'){ 
     *background = 1; 
     inputBuffer[i] = '\0'; 
    } 
    } 
    }  

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/+1];/* command line (of 80) has max of 40 arguments */ 
    pid_t pid; 
    char iBuffer2[MAX_LINE]; 
    int i; 

    /* set up the signal handler */ 
    struct sigaction handler; 
    handler.sa_handler = handle_SIGINT; 
    sigaction(SIGINT, &handler, NULL); 
    while (1){   /* Program terminates normally inside setup */ 
    background = 0; 
    printf("COMMAND->"); 
    fflush(0); 
    setup(inputBuffer, args, &background);/* get next command */ 

    if ((strcmp(args[0],"r")==0) && (ct==1)) 
    { 
    fflush(0); 
    rFlag = 1; 
    background = 0; 
    printf("strlen=%i", strlen(history[0])); 
    setup(history[0], args, &background); 
    printf("AFTER"); 

} 

if (strcmp(args[0],"exit")==0)break; //exits if args[0]=="exit" 
pid_t pid = fork(); 
if (pid < 0) { //Error Occured 
    fprintf(stderr, "Fork Failed"); 
    exit(-1); 
} 
else if (pid == 0) {//Child Process 
    execvp(args[0], args); // Execute command in args 
    printf("%s: Command not found.\n", args[0]); //If invalid command 
    exit(0); 
} 
    else { // Parent Process 
if (background == 0) { // case with No '&' 
    wait(NULL); 
} 
    } 
printf("\nFinish\n"); 
} 
} 
+3

你甚至使用过GDB吗? – 2010-11-20 01:23:12

+1

你有没有尝试缩进代码? – 2010-11-20 05:18:05

回答

2

如果您打算使用低级别的I/O,那么在对数据读取执行任何字符串操作之前,在执行read()之后NUL终止数据是您的责任。

length = read(STDIN_FILENO, inputBuffer, MAX_LINE-1); 
if (length > 0) 
    inputBuffer[length] = '\0'; 
else 
    inputBuffer[0] = '\0'; 

但是,read()可能不是你想要使用的第一个地方,因为你似乎期望一次给出一行。尝试使用fgets()代替。