I would like to write a program that will eventually replicate the functionality of this
program1 | program | programX
So I would like to redirect programX's output into programX+1's input.
For the sake of simplicity, I would like to start off with only two programs and a single pipe.
In pseudocode, my approach looks like this:
1. create a pipe for communication between child1 and child2
2. fork parent to create child1 and fork parent again to create child2
3. close unneeded pipe ends in children
4. redirect the output of execvp() from child 1 into the write-end of the pipe via dup2, so that child2 receives whatever that program puts out
5. child2 reads the pipe and receives output from program of child1
6. execute execvp() with the received data
So far so good, here is what I currently have:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define READ 0
#define WRITE 1
int main(int argc, const char * argv[])
{
//create a unidirectional pipe
int aPipe[2];
if(pipe(aPipe)){
perror("pipe call");
exit(EXIT_FAILURE);
}
//create child 1 ("sender")
pid_t child_pid = fork();
if(child_pid < (pid_t)0)
{
perror("fork call failed");
exit(EXIT_FAILURE);
}
else if(child_pid == (pid_t) 0){
//in child1
close(aPipe[READ]);
//get actual arguments from argv array
const char **realArgs = malloc(sizeof(char *) * (argc-1));
for(int i=1;i<argc;i++){
realArgs[i-1] = argv[i];
}
//redirect standard output into write-end of the pipe
dup2(aPipe[WRITE], STDOUT_FILENO);
close(aPipe[WRITE]);
execvp(argv[0], realArgs);
//exec call failed
exit(EXIT_FAILURE);
}
//parent
//create second child ("receiver")
pid_t child2_pid = fork();
if(child2_pid == (pid_t)0){
//close unneeded pipe end
close(aPipe[WRITE]);
char buffer[1024];
char **argv2 = malloc(sizeof(char *));
while (read(aPipe[READ], buffer, sizeof(buffer)) != 0)
{
argv2[0] = buffer;
printf("buffer = %s", buffer);
//execvp("sort", argv2);
}
close(aPipe[READ]);
exit(EXIT_SUCCESS);
}
//close unneeded pipe ends, parent does not need the pipe
close(aPipe[WRITE]);
close(aPipe[READ]);
exit(EXIT_SUCCESS);
return 0;
}
That achieves almost what I am trying to do, but the output in child2 seems to write into the pipe again and that results in writing into its own pipe. I think, and I may be completely wrong here, that (despite closing the write end in child2) via printf it writes into its own pipe (as I redirected STDOUT into the write end of the pipe) and reads that again. So the output looks like this
When I run the program with parameters who
and sort
myProg who sort
I get the following output:
buffer = buffer = martine****** console Apr 24 12:59
EDIT:
How do I set the input for the sort command in execvp("sort", argsArr); ? sort usually takes in a filename, so how do I go about that ?