I'm making a shell simulator for an operating systems course homework. We were asked to add a "history" command that when typed, should print a list of commands that the user entered.
I decided to implement it using a history array that allocates dynamically more memory depending on the size of the new command.
Here is my code:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 100
//comment
int main(void)
{
close(2);
dup(1);
char command[BUFFER_SIZE];
char* hist = NULL;
// int counter = 0;
while (1)
{
fprintf(stdout, "my-shell> ");
memset(command, '\0', BUFFER_SIZE);
fgets(command, BUFFER_SIZE, stdin);
if(strncmp(command, "exit", 4) == 0)
{
break;
}
//alocate memory for the current position in the hist array
if(hist == NULL){
hist = (char*)malloc(sizeof(char)*strlen(command));
}
else{
hist = realloc(hist,sizeof(char)*strlen(command));
}
strcat(hist,command);
printf("the size of the boy: %d\n",(int) strlen(hist));
// counter = strlen(command);
int pid = fork();
char *argv[BUFFER_SIZE];
char *pch;
pch = strtok(command, " \n");
int i;
for(i=0; pch != NULL; i ){
argv[i] = pch;
pch = strtok(NULL, " \n");
}
argv[i] = NULL;
int hasAmpersand = 0;
//check if the last entered character was '&'
if(*argv[i-1]=='&'){
// printf("entered &:");
hasAmpersand = 1;
//replace it with '\0'
argv[i-1] = NULL;
}
if(pid == 0){ //child process execute sys call
if(strncmp(argv[0],"history",7) == 0){
printf("%s\n", hist);
exit(1);
}
else{
execvp(argv[0], argv);
printf("\nbad syntax\n");
}
}
else{
if(!hasAmpersand){ //wait for child
while(wait(NULL) != pid);
}
}
}
free(hist);
return 0;
}
The implementation works for up to 6 commands stored in hist but it crashed with the error
realloc(): invalid next size
aborted
I was wondering what causes the issue and I'd love suggestions on fixing it. Thanks.
CodePudding user response:
The second parameter of realloc should be the new size of the entire block, not just the size of data you are "adding" to memory area.
hist = realloc(hist, currentHistSize sizeof(char)*strlen(command));
Make sure you name currentHistSize as you want.
CodePudding user response:
You need room for the trailing string terminator '\0'
, so add one to the allocated size:
hist = malloc(sizeof(char)*strlen(command) 1);
The argument to realloc also needs to be adjusted. Also you probably want to remove the trailing newline after calling fgets.