Does the child process redirect standard output to the parent process?
I am studying OS exam on Tuesday. To prepare, I'm trying to simulate a command line pipe using a C program.
The program is pretty simple. I make a pipe and then deploy a child process.
The child process redirects standard output to the end of the record, closes the file descriptors for the pipe, and then executes the command ( ls
, in this case).
The parent process waits for the child process to exit, redirects standard input to the end of the output on the pipe, closes the file descriptors for the pipe, and then executes the command ( grep 'school'
in this case).
When I execute a command via the command line with using ls | grep 'school'
, a line appears that says "school" is being printed to standard output, which makes sense given that there is a directory in the directory where I run the program in the name of that.
When I run the program I created, I don't get any error messages, but it doesn't output any results.
The only thing I can think of as interfering with work is that redirecting standard output to the child process somehow affects the parent's command output, but I'm pretty sure it shouldn't be.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main() {
int fds[2];
int pipe_val, close_val, write_val, dup_val, status;
pid_t pid;
char *error;
pipe_val = pipe(fds);
if (pipe_val) {
fprintf(stderr, "Failed to prepare pipe.\n");
return -1;
}
pid = fork();
if (pid == -1) {
fprintf(stderr, "Failed to fork a child process.\n");
return -1;
} else if (pid == 0) {
dup_val = dup2(fds[1], STDOUT_FILENO);
if (dup_val) {
error = strerror(errno);
fprintf(stderr, "Failed to redirect standard output in child process because %s\n", error);
exit(1);
}
close_val = close(fds[0]);
if (close_val) {
fprintf(stderr, "Failed to close read-end of pipe in child process.\n");
exit(1);
}
close_val = close(fds[1]);
if (close_val) {
fprintf(stderr, "Failed to close write-end of pipe in child process.\n");
exit(1);
}
execl("/bin/ls", "ls", NULL);
fprintf(stderr, "Failed to execute command in child process.\n");
exit(1);
} else {
wait(&status);
dup_val = dup2(fds[0], STDIN_FILENO);
if (dup_val) {
error = strerror(errno);
fprintf(stderr, "Failed to redirect standard input in parent process because %s.\n", error);
return -1;
}
close_val = close(fds[0]);
if (close_val) {
fprintf(stderr, "Failed to close read-end of the pipe in the parent process.\n");
return -1;
}
close_val = close(fds[1]);
if (close_val) {
fprintf(stderr, "Failed to close write-end of the pipe in the parent process.\n");
return -1;
}
execl("/bin/grep", "grep", "school", NULL);
fprintf(stderr, "Failed to execute the command in the parent process.\n");
return -1;
}
}
source to share
Your first problem is that you haven't included all the required headers for the functions you are using. strerror
demands <string.h>
and wait
demands <sys/wait.h>
.
If you are compiling gcc, always use gcc -Wall
and read warnings. In this case, he would have complained about the implicit declaration strerror
.
Since strerror
it was not declared, the compiler assumes that it returns int
, which is incorrect. If you run the program on 64-bit Linux x86 int
does not match the pointer returned strerror
. This becomes a fatal problem when you pass the result strerror
in fprintf
with a format %s
, because the pointer was misinterpreted as an int and then converted back to a pointer, eventually with a dummy value. fprintf
segfaults and you will never see an error message.
Include the correct headers and you will see an error message that will lead you to the next problem you should fix.
source to share