2010-11-20 9 views
2

Je suis en train d'écrire du code pour un shell c simpliste. Il stocke l'historique de la dernière commande. Si 'r' est entré en tant que commande, alors il devrait exécuter la commande la plus récente de l'historique. En outre, si 'r x' est entré, où 'x' est la première lettre de la commande à exécuter à partir de l'historique, alors il exécute la commande la plus récente commençant par cette lettre.erreur de segmentation dans une coque simpliste

J'ai rencontré un problème de copie de l'historique à l'inputBuffer; cela donne une erreur de segmentation quand j'essaye de le faire.

Voici le code (c'est désordonné que j'ai essayé beaucoup de choses différentes dans l'espoir de le réparer). Tout conseil serait grandement apprécié!

#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

Avez-vous même dû utiliser GDB? –

+1

Et avez-vous essayé d'indenter le code? –

Répondre

2

Si vous utilisez des E/S de bas niveau, il est de votre responsabilité de mettre fin aux données après avoir lu() avant d'effectuer des opérations sur les données lues.

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

Mais read() est sans doute pas ce que vous voulez être en utilisant en premier lieu, que vous semblez attendre à donner une ligne à la fois. Essayez d'utiliser fgets() à la place.