Solved

Using pipes to pass the output to parent

Posted on 2008-10-26
12
460 Views
Last Modified: 2013-12-26
I need to write a code that pass the output of "ls -l" back to parent using pipe. The ls- l will be executed by child after the fork process. Previously I succeeded in using fork() and execl to call another program to do a similar read() and write() system call that mimic "cat" function. This is how i think my program will look like for pipe

Declare variables
Fork()
pipe()
execl("/bin/ls","ls","-l",0);
??

I am stuck at the part, where I do not know how to assign the output from execl() to string. I am thinking of using a string variable to store the result OR you suggest to use FILE to store the result and then use the read and write function to get back all the output ?

Other thing, please guide me on how to write this, I am confuse with pipes and I have been searching quite a lot of resources but I still failed to understand pipes in details.

Thanks for your help
0
Comment
Question by:msh79
  • 5
  • 5
  • 2
12 Comments
 
LVL 12

Expert Comment

by:hfraser
ID: 22807111
Pipes are used to communicate between processes. They can be "named pipes", created ahead of time and accessed as file in the filesystem (see mkfifo) or dynamically (as in ls -1 | wc to get he number of files in a directory). Your program is doing the latter by creating an un-named pipe and creating a child thread to talk with.

The pipe function creates the pipe, and as with any pipe there are two ends. Typically, the parent will close the output handle, and listen on the input. The child does the opposite, closing the input and writing to the output, mimicing the stdin/stdout idea. In your example, you'll want to replace the stdout of the child process with it's half the pipe (see the response by ozo in question 21219592 for an example).

These steps are packaged into the popen function, but it invokes a shell to execute a command, introducing some additional overhead you may not want.
0
 

Author Comment

by:msh79
ID: 22807290
When I try to search for 21219592, it only list my thread. So far I haven't succeeded in opening ozo thread for this similar question. I am in the midst of writing the code and let's me know if I am in the right direction.

a) Can I store execl result in a string so read() can get the input while Child is performing the action
b) How do I continue on the parent side to get the output

Attach is the source code. And I would love to read Ozo answer too. Pls provide guidenace
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
 
void list_child(int fd[]);
void list_parent(int fd[]);
 
int main ()
{
  int pid,status,fd[2];
  printf("This program list through pipe");
 
  /*create a pipe*/
  status=pipe(fd);
  if (status==-1) {
     perror("pipe");
     exit(1);
  }
 
  /*Fork to child process*/
  pid = fork();
 
  switch (pid) {
     case -1: perror("fork");
              break;
     case 0:  list_child(fd);
              break;
     default: list_parent(fd);
              break;
 
     }
  return 0;
}
 
void list_child(int pid[]){
   char listdir[];
   int status;
 
   /*close un-needed write part of the pipe*/
   close(fd[1]);
 
   /*now execl to list the directory*/
   listdir=execl("/bin/ls","ls","-l",0);
 
   /*?? not sure how to write to read data in string from execl */
   while ((status=read(fd[0],listdir,1))>0){
   }
 
   exit(0);
 
 
}
 
void list_parent(int fd[]);
{
     int status;
 
     /*close the un-needed read part of the pipe*/
     close(fd[0]);
 
    /*write back all the data from listdir or child*/
    // ?? not how to proceed
    
   
 
}

Open in new window

0
 
LVL 12

Expert Comment

by:hfraser
ID: 22807757
I need to work on linking other contributor's work. Here's the full link to ozo's response. It contains examples you're looking for.

http://www.experts-exchange.com/Programming/Languages/C/Q_20336027.html?sfQueryTermInfo=1+execl+ozo+pipe
0
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 

Author Comment

by:msh79
ID: 22807876
I read Ozo contribution, I am confuse with filedes[]. For my single un-named pipe, do I need to create 2 separate filedes[] and also do I need to use dup function ?

Do you have much more simple example that I could digest - I am still beginner :). Thanks for your answer so far, really appreciate it
0
 
LVL 12

Expert Comment

by:hfraser
ID: 22808009
Try this. It's almost exactly what you want.

http://www.dgp.toronto.edu/~ajr/209/notes/procfiles/pipe-example.c
0
 

Author Comment

by:msh79
ID: 22808997
Hello hfraser, I am started able to code a bit. I could run the program and get the output but I am not sure whether the code is correct.

a) Is the execl is executed by the child (I put a pid and printf statement to check) ?
b) Do you think this is the correct way for parent to read the output from the pipe.

My understanding is there is only 1 pipe (upstream is at p[1] - write on the left end of pipe) & downstream is at p[0] - read on the right end of the pipe).

I am just afraid the code only execute because I use execl where it was not done by child ?

Please evaluate

Cheers !
#include <stdio.h>
#include <unistd.h>
#define BUFSIZE 100
 
int main()
{
int count,p[2],status;
char buffer[BUFSIZE];
 
pipe(p);
 
/*fork child*/
if (fork()==0){
  write(p[1],buffer,15);
  execl("/bin/ls","ls","-l",0);
  count=read(p[0],buffer,BUFSIZE);
 
  }
  /*Parent writing out the output*/
  write(1,buffer,count);
  wait(&status);
 
  return 0;
}

Open in new window

0
 
LVL 84

Expert Comment

by:ozo
ID: 22809272
for what you are doing, it sounds like popen may be an easier way to do it.
0
 

Author Comment

by:msh79
ID: 22809315
Ozo - thanks for stepping in. You are the wizard, hfraser mentioned before :D

He also recommend popen, but my assignment have to use the basic function to demonstrate how a pipe works with child and output back to parent

Please share some ideas, I am running out of ideas.
0
 
LVL 12

Expert Comment

by:hfraser
ID: 22809462
Try something like this:

        if (fork()==0){
                close(1);
                dup (p[1]);
                execl("/bin/ls","ls","-l",0);
                exit(0);
        }
        else {
                close(0);
                dup (p[0]);
                while (read(0, &c, 1) >0) {
                        write(1,&c,1);
                }
                exit(0);
        }

Standard I/O channels are 0 for stdin, and 1 for stdout. The parent has to replace it's stdin with one end of the pipe, and the child does the opposite.

0
 
LVL 84

Accepted Solution

by:
ozo earned 250 total points
ID: 22809513
#include <stdio.h>
#include <unistd.h>
main(){
#define in 0
#define out 1
int pipefd[2];
int pid;
char string[10000];
int l;
pipe(pipefd);
if( (pid=fork()) < 0 ){
     perror("fork");
}else if( pid==0 ){
    close(pipefd[0]);
    dup2(pipefd[1],out);
    execl("/bin/ls","ls","-l",0);
    perror("execlp ls");
}
close(pipefd[1]);
dup2(pipefd[0],in);
l=read(in,string,sizeof(string));
write(fileno(stdout),string,l);
}
0
 

Author Comment

by:msh79
ID: 22810807
Thanks guys - both the logic seems to be identical. Let me clarify a few things before I close this thread

1. Could I accept both the answers given - Ozo & hFraser as both of you have been very helpful so I assume I need to click on Accept Multiple Solutions on both entry. Correct ?

2. I read the article http://www.ftt.co.uk/tutorials/Sysprog_tutorial3.html, so from the above solutions the pipe - 0 or 1 (input and output). Can it be the other way ? Sorry for the dumb question - refer to attached file

3. Also do you think it looks better if I add these codes to close the pipe to close both end of the pipe and wait for child to finish

close(fd[0]);
close(fd[1]);
wait(0);


Thanks so much
programmer.gif
0
 
LVL 12

Expert Comment

by:hfraser
ID: 22811079
The answer goes to ozo, who I tried to reference in the first place. I just messed up with the link.

The pipe is just a pipe. Either end can be used for reading or writing.

Closing both ends isn't necessary, since they're destroyed when the process exits. But it is cleaner coding and does make a difference if the pipe was being re-used in a more complex program. Same applies to the wait.
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
wordsFront challenge 8 88
PHP question(s) about order of output 9 62
rhino JavaScript import, load 25 82
"Black Box" Testing of Control System Software 2 49
Article by: Nadia
Suppose you use Uber application as a rider and you request a ride to go from one place to another. Your driver just arrived at the parking lot of your place. The only thing you know about the ride is the license plate number. How do you find your U…
Article by: Nadia
Linear search (searching each index in an array one by one) works almost everywhere but it is not optimal in many cases. Let's assume, we have a book which has 42949672960 pages. We also have a table of contents. Now we want to read the content on p…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

774 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question