Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Using pipes to pass the output to parent

Posted on 2008-10-26
12
Medium Priority
?
465 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 1000 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

Survive A High-Traffic Event with Percona

Your application or website rely on your database to deliver information about products and services to your customers. You can’t afford to have your database lose performance, lose availability or become unresponsive – even for just a few minutes.

Question has a verified solution.

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

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

704 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