我正在编写一个简单的c shell代码。它存储了最后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");
}
}
答案 0 :(得分:2)
catchsegv
可用于创建堆栈跟踪。 http://www.linuxfromscratch.org/lfs/view/stable/chapter06/glibc.html
答案 1 :(得分:2)
如果您打算使用低级别的i / o,那么在对读取的数据执行任何字符串操作之前,NUL在执行read()之后终止数据是您的责任。
length = read(STDIN_FILENO, inputBuffer, MAX_LINE-1);
if (length > 0)
inputBuffer[length] = '\0';
else
inputBuffer[0] = '\0';
但是read()可能不是你想要首先使用的东西,因为你似乎希望一次得到一条线。尝试使用fgets()代替。