ошибка сегментации в упрощенной оболочке - PullRequest
2 голосов
/ 20 ноября 2010

Я пишу код для упрощенной оболочки c.Он хранит историю последних 10 команд.Если в качестве команды введена буква «r», то она должна выполнить самую последнюю команду из истории.Кроме того, если введено «rx», где «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");
}
}

Ответы [ 2 ]

2 голосов
/ 20 ноября 2010

Если вы собираетесь использовать низкоуровневый ввод-вывод, то вы несете ответственность за NUL-завершение данных после выполнения read () перед выполнением любых строковых операций с данными.

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

Ноread (), вероятно, не то, что вы хотите использовать в первую очередь, так как вы, похоже, ожидаете получить строку за раз.Попробуйте использовать fgets ().

2 голосов
/ 20 ноября 2010

catchsegv может использоваться для создания трассировки стека, когда программа завершается с ошибкой сегментации.http://www.linuxfromscratch.org/lfs/view/stable/chapter06/glibc.html

...