Solved

Using pipes to pass the output to parent

Posted on 2008-10-26
12
461 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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Help with my python script 6 166
sumHeights2  challenge 7 117
Choosing the right language for new project 8 66
Detect file exist or not 3 180
If you haven’t already, I encourage you to read the first article (http://www.experts-exchange.com/articles/18680/An-Introduction-to-R-Programming-and-R-Studio.html) in my series to gain a basic foundation of R and R Studio.  You will also find the …
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

830 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