July 26th, 2003, 11:44 PM
How to read input from pipe and display stdout?
I have created two child processes. I am trying to tell one process to write a command to the pipe, and I want the other child to read from the pipe and print it out to the stdout. I want first child to write the result of ps command with argument -aef to pipe, and the second child to look at the pipe's output and run grep command to print all processes running csh. I have used execl("usr/bin/ps -aef", "ps",0); to write the result of ps to the pipe, but I don't know how to make the second child read it and pick processors with csh??????????
I would appreciate your help.
switch(pid2=fork())// This one writes to pipe
case -1: //error
case 0: close(1);
execl("usr/bin/ps -aef", "ps",0);
switch(pid3=fork())// This one reads from pipe and prints to stdout
case -1: //error
case 0: close(0);
//Need to read output from pipe and print to stdout???????
July 28th, 2003, 12:27 AM
It'll be a couple days before I'll have time to play with this, but a couple things might help in the meantime:
1. pipe requires an array of file descriptors, not a single fd. The declaration should read:
2. You read from the pipe with the read function, for which you will need to supply a buffer. A month or two or three ago there was a thread on creating a front-end for the bc utility and in which I uploaded an example which has two pipes running between the parent and a child.
That thread was "Creating a frontend for bc" circa 16 June. This link should get you there: http://forums.devshed.com/t65312/s6b...70aa9dcaf.html
Last edited by dwise1_aol; July 28th, 2003 at 10:59 AM.
July 29th, 2003, 03:54 PM
Another more serious problem was that your execl() function call was wrong. The first parameter is the program to be executed and the remaining parameters are the argv that will be passed to that program. Including the options in the first argument makes the shell think that's part of the name and so it cannot find that program. Here's how it should be (keeping your system's path to ps):
execl("usr/bin/ps", "ps", "-aef", 0);
Now, if you don't test the return value of execl for an error (ie, if it returns -1), then you'd never know that the call failed, which is why the pipe read in the reader process will fail. Error-checking is very important, especially when you are trying to track down a problem.
Here's the listing that I got running. It doesn't terminate properly, but I have other more pressing matters that keep me from figuring that one out. Run ps in another shell to see what's happening. It looks like the pid2 process isn't terminating properly, which causes the pipe to remain open and thus prevents the pid3 process from terminating.
#define BUF_SIZE 256
int pipefd; // two file descriptors:
int pid2, pid3;
// open the pipe
if (pipe(pipefd) == -1)
perror("pipe creation error");
// initialize the buffer
printf("ppid == %d\n",getpid());
switch(pid2 = fork( ))
perror("pid2 fork error");
dup(pipefd); // redirect stdout to the pipe
close(pipefd); // close the read end
printf("pid2 executing command\n");
if (execl("/bin/ps", "ps","-edf",0) == -1)
perror("execl call failed");
exit(1); /* should never reach here */
printf("%d created pid2 == %d\n",getpid(),pid2);
// fork a child process
switch(pid3 = fork( ))
perror("pid3 fork error");
close(pipefd); // close the write end of the pipe
/* read from the pipe until it is closed on the other
end (indicated by read returned zero) */
bytes_read = read(pipefd,buf,BUF_SIZE);
if (bytes_read == -1)
perror("pid3: read pipe error");
write(1,buf,bytes_read); // echo data to stdout
} while (bytes_read > 0); // ie, for as long as something is read
printf("%d created pid3 == %d\n",getpid(),pid3);