1

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 ?

12
  • Your while loop seems to go 2 iterations. The first iteration, buffer is empty, so the program writes buffer=. The second iteration it gets data and writes buffer = martine****** console Apr 24 12:59. Commented Apr 24, 2014 at 14:52
  • this is a common homework question and a common question on so. If you do a search you should find many questions and answers about this task. Commented Apr 24, 2014 at 14:58
  • @KlasLindbäck Well, actually, if I delimit the output with ticks, I get something like buffer = "buffer = "martine****** console Apr 24 12:59"". So it seems like it does get the stdout into the pipe, which is very strange. Commented Apr 24, 2014 at 14:59
  • @Hogan I have seen 3 questions on here, none of which actually helped me. For example, the sort command (see edited question) takes a filename as input, how do I execvp("sort", ?fileDescriptor? ) ? Commented Apr 24, 2014 at 15:00
  • With no FILE, or when FILE is -, sort reads from standard input. Commented Apr 24, 2014 at 15:02

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.