I am implementing a shell.
When attempting a command other than changing directories, execvp()
runs, the child terminates and a new child is created. When I change directories, the child does not terminate and a new child is created. Here is a sample of my code:
for(;;) {
printf("bash: ");
parse();
...
pid_t pid = fork()
if (pid == 0)
if (!strcmp(line[0], "cd"))
if (!line[1]) (void) chdir(getenv("HOME"));
else (void) chdir(line[1]);
else execvp(line[0], line);
...
if (pid > 0) {
while (pid == wait(NULL));
printf("%d terminated.\n", pid);
}
}
cd ../; ls;
runs correctly, except I have to Ctrl+D
twice to end the program.
Though, if I pipe the same information (ie. mybash < chdirtest
), it runs correctly once, terminates the child, runs again except in the original directly, then terminates the final child.
cd
should not be invoked through a child process, the shell itself should change its current directory (that's the property of an internal command: modify the process of the shell itself).
A (primitve) shell should looks like:
for(;;) {
printf("bash: ");
parse();
// realize internal commands (here "cd")
if (!strcmp(line[0], "cd")) {
if (!line[1]) (void) chdir(getenv("HOME"));
else (void) chdir(line[1]);
continue; // jump back to read another command
}
// realize external commands
pid_t pid = fork()
if (pid == 0) {
execvp(line[0], line);
exit(EXIT_FAILURE); // wrong exec
}
// synchro on child
if (pid > 0) {
while (pid == wait(NULL));
printf("%d terminated.\n", pid);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With