#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    5
    Rep Power
    0

    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.

    int pipefd;
    pipe(pipefd);
    switch(pid2=fork())// This one writes to pipe
    case -1: //error
    case 0: close(1);
    dup(pipefd[1]);
    close(pipefd[0]);
    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);
    dup(pipefd[0]);
    close(pipefd[1]);
    //Need to read output from pipe and print to stdout???????
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    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:
    int pipefd[2];

    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.

    EDIT:
    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 09:59 AM.
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    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.
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <wait.h>
    
    #define BUF_SIZE  256
    
    int main(void)
    {
            char buf[BUF_SIZE];
            int pipefd[2];  // two file descriptors:
            int pid2, pid3;
            int bytes_read;
    
            // open the pipe
            if (pipe(pipefd) == -1)
            {
                    perror("pipe creation error");
                    exit(1);
            }
    
            // initialize the buffer
            memset(buf,0,BUF_SIZE);
    
            printf("ppid == %d\n",getpid());
    
            switch(pid2 = fork( ))
           {
            case -1:
                    perror("pid2 fork error");
                    exit(1);
            case 0:
                close(1);
                dup(pipefd[1]);   // redirect stdout to the pipe
                close(pipefd[0]); // 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 */
            default:
                printf("%d created pid2 == %d\n",getpid(),pid2);
           }
    
            // fork a child process
            switch(pid3 = fork( ))
           {
            case -1:
                    perror("pid3 fork error");
                    exit(1);
            case 0:
                close(pipefd[1]);  // close the write end of the pipe
                /* read from the pipe until it is closed on the other
                     end (indicated by read returned zero)  */
                do
                {
                    bytes_read = read(pipefd[0],buf,BUF_SIZE);
                    if (bytes_read == -1)
                        perror("pid3: read pipe error");
                    else
                        write(1,buf,bytes_read);  // echo data to stdout
                } while (bytes_read > 0);  // ie, for as long as something is read
                printf("pid3 exiting\n");
                exit(0);
            default:
                printf("%d created pid3 == %d\n",getpid(),pid3);
           }
    
    //    waitpid(pid3,NULL,0);
    
        return 0;
    }

IMN logo majestic logo threadwatch logo seochat tools logo