I'm trying to write a history feature to a very simple UNIX shell that will list the last 10 commands used when control-c is pressed. A user can then run a previous command by typing r x, where x is the first letter of the command. I'm having quite a bit of trouble figuring out what I need to do, I have very little C experience, but I know a fair bit of C++. If anyone could give me some suggestions as to where to start, I'd appreciate it. Here is the code I'm working from right now.
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
#define BUFFER_SIZE 50
char buffer[BUFFER_SIZE];
/* the signal handling function */
void handle_SIGINT()
{
write(STDOUT_FILENO, buffer, strlen(buffer));
}
/**
- 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 setup(char inputBuffer[], char *args[],int background)
{
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;
/* 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 the 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;
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()
{
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];
pid_t pid;
/* 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(" sh>\n");
setup(inputBuffer,args,&background); / get next command */
/* the steps are:
\(1\) fork a child process using fork\(\) */
pid = fork\(\);
if\(pid == 0\)\{ /* child process \(2\) the child process will
invoke execvp\(\)*/
execvp\(args[0], args\);
exit\(0\);
\}
else if\(pid > 0\)\{ /*parent process \(3\) if background == 1, the parent
will wait, otherwise returns to the setup\(\) function.
*/
if\(background == 1\)\{
wait\(NULL\);
\}/* if */
\}/* if */
}
}