I am writing a shell in C/C . When I try changing the directory with chdir(const char*)
, the shell starts to lag. The shell works very good until somthing like cd ..
is typed. Then when I try typing ls
, it says it cannot execute couldn't execute: l
(not ls
).
to build: g main.cc -lreadline
#include <stdio.h>
#include <readline/readline.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string>
#define clear printf("\033[H\033[J")
char** getInput(char* input)
{
char** command = (char**) malloc(8 * sizeof(char*));
char* separator = " ";
char* parsed;
int index = 0;
parsed = strtok(input, separator);
while (parsed != NULL)
{
command[index] = parsed;
index ;
parsed = strtok(NULL, separator);
}
command[index] = NULL;
return command;
}
int main()
{
char** command;
char* input;
pid_t child_pid;
int stat_loc;
bool loop = true;
do
{
input = readline("");
command = getInput(input);
child_pid = fork();
if (child_pid < 0)
{
printf("Fork Failed\n");
exit(0);
}
if (strncmp(command[0], "cd\n", 2) == 0)
{
if (chdir(std::string(command[1]).c_str()) < 0)
printf("Couldn't execute: %s\n", command[1]);
continue;
}
else if (child_pid == 0)
{
execvp(command[0], command);
printf("couldn't execute: %s\n", input);
}
else waitpid(child_pid, &stat_loc, WUNTRACED);
free(input);
free(command);
} while (loop);
}
CodePudding user response:
You are forking at the wrong position, resulting in spawning multiple children when using command cd
. In addition to that, the continue
for command cd
prevents freeing input
and command
. Also, the child needs to break the loop to exit after running the command.
So this:
child_pid = fork();
if (child_pid < 0)
{
printf("Fork Failed\n");
exit(0);
}
if (strncmp(command[0], "cd\n", 2) == 0)
{
if (chdir(std::string(command[1]).c_str()) < 0)
printf("Couldn't execute: %s\n", command[1]);
continue;
}
else if (child_pid == 0)
{
execvp(command[0], command);
printf("couldn't execute: %s\n", input);
}
else waitpid(child_pid, &stat_loc, WUNTRACED);
should be:
if (strncmp(command[0], "cd\n", 2) == 0)
{
if (chdir(std::string(command[1]).c_str()) < 0)
printf("Couldn't execute: %s\n", command[1]);
free(input);
free(command);
continue;
}
child_pid = fork();
if (child_pid < 0)
{
printf("Fork Failed\n");
exit(0);
}
else if (child_pid == 0)
{
execvp(command[0], command);
printf("couldn't execute: %s\n", input);
loop = false;
// or:
//free(input);
//free(command);
//exit(0);
}
else waitpid(child_pid, &stat_loc, WUNTRACED);