Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 466
  • Last Modified:

Using pipes to pass the output to parent

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
msh79
Asked:
msh79
  • 5
  • 5
  • 2
1 Solution
 
Hugh FraserConsultantCommented:
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
 
msh79Author Commented:
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
 
Hugh FraserConsultantCommented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
msh79Author Commented:
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
 
Hugh FraserConsultantCommented:
Try this. It's almost exactly what you want.

http://www.dgp.toronto.edu/~ajr/209/notes/procfiles/pipe-example.c
0
 
msh79Author Commented:
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
 
ozoCommented:
for what you are doing, it sounds like popen may be an easier way to do it.
0
 
msh79Author Commented:
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
 
Hugh FraserConsultantCommented:
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
 
ozoCommented:
#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
 
msh79Author Commented:
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
 
Hugh FraserConsultantCommented:
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

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!

  • 5
  • 5
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now