In: Computer Science
In C language,
Write a program called minishell that creates two child
processes:
one to execute 'ls -al' and the other to execute
‘grep minishell.c’.
After the forks, the original parent process waits for both
child processes to finish before it terminates. The parent should
print out the pid of each child after it finishes. The standard
output of 'ls -al' process should be piped to the input to the
'grep minishell.c' process. Make sure you close the unnecessary
open files for the three processes. The output should be the one
line that includes the directory entry for minishell.c. You will
need to call the source file minishell.c for this to work
properly.
Please comment thoroughly so i can follow the logic.
ANSWER:--
GIVEN THAT:--
Answering the fist part of the question where the parent should wait for the two child process to finish
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid1, pid2;
int status;
// create the first child process
if ((pid1 = fork()) < 0) {
perror("error forking first child");
return -1;
}
if (pid1 == 0) {
// first child process - execute 'ls -al'
char *args[]={"/bin/ls","-al", NULL};
execvp(args[0], args);
}
//control does not get here since execvp has replaced the program
image
// again fork
if ((pid2 = fork()) < 0) {
perror("error forking second child");
return -1;
}
if (pid2 == 0) {
// second child process execute 'grep main minishell.c'
char *args[]={"/bin/grep","main", "minishell.c", NULL};
execvp(args[0], args);
}
wait(&status);
fflush(stdout);
if (pid2 > 0 && pid1 > 0) {
printf("PID of the first child: %d\n", pid1);
printf("PID of the second child: %d\n", pid2);
}
return 0;
}
Now coming to the second part of the question the question seems little incorrect. Ideally to expect the desired output the grep pattern should be "grep minishell". Considering that the following code does the trick -
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid1, pid2;
int status;
int pipefds[2];
int ret;
// create a pipe where the child processes could
communicate
ret = pipe(pipefds);
if (ret < 0) {
perror("error creating pipe");
return -1;
}
// create the first child process
if ((pid1 = fork()) < 0) {
perror("error forking first child");
return -1;
}
if (pid1 == 0) {
// first child process - execute 'ls -al'
char *args[]={"/bin/ls","-al", NULL};
// close the stdout of the process; redirect to the pipe write
end
close(1);
dup2(pipefds[1], 1);
//close read end of pipe
close(pipefds[0]);
execvp(args[0], args);
}
//control does not get here since execvp has replaced the program
image
// again fork
if ((pid2 = fork()) < 0) {
perror("error forking second child");
return -1;
}
if (pid2 == 0) {
// second child process execute 'grep main minishell.c'
char *args[]={"/bin/grep","minishell",NULL};
// redirect the stdin to the read end of pipe
close(0);
dup2(pipefds[0], 0);
//close write end of pipe
close(pipefds[1]);
execvp(args[0], args);
}
// close both pipefds in the parent since it never uses it
close (pipefds [0]);
close (pipefds [1]);
wait(&status);
fflush(stdout);
return 0;
}