simple pipe

I have got the below code and is working fine!!!
Example of running the below program is
$> ./a.out who less

Basically my code does the same as "who | less"

My Question
========
if I change
    if ( pid > 0 ){         /* parent will exec av[2]   */
to
    if ( pid == 0 ){         /* child will exec av[2]   */
then everything will go haywire!

Why?



/* pipe.c      
 *  * Demonstrates how to create a pipeline from one process to another
 *  * Takes two args, each a command, and connects
 *    av[1]'s output to input of av[2]
 *  * usage: pipe command1 command2
 *    effect: command1 | command2
 *  * Limitations: commands do not take arguments
 *  * uses execlp() since known number of args
 *  * Note: exchange child and parent and watch fun
 */
#include    <stdio.h>
#include    <unistd.h>

#define oops(m,x)   { perror(m); exit(x); }

main(int ac, char **av)
{
    int thepipe[2],         /* two file descriptors */
        newfd,              /* useful for pipes */
        pid;                /* and the pid      */

    if ( ac != 3 ){
        fprintf(stderr, "usage: pipe cmd1 cmd2\n");
        exit(1);
    }
    if ( pipe( thepipe ) == -1 )        /* get a pipe       */
        oops("Cannot get a pipe", 1);

    /* ------------------------------------------------------------ */
    /*  now we have a pipe, now let's get two processes     */

    if ( (pid = fork()) == -1 )         /* get a proc   */
        oops("Cannot fork", 2);

    /* ------------------------------------------------------------ */
    /*  Right Here, there are two processes         */
    /*             parent will read from pipe           */

    if ( pid > 0 ){         /* parent will exec av[2]   */
        close(thepipe[1]);  /* parent doesn't write to pipe */                                                              
                                                                                                                           
        if ( dup2(thepipe[0], 0) == -1 )                                                                                    
            oops("could not redirect stdin",3);                                                                            
                                                                                                                           
        close(thepipe[0]);  /* stdin is duped, close pipe   */                                                              
        execlp( av[2], av[2], NULL);                                                                                        
        oops(av[2], 4);                                                                                                    
    }                                                                                                                      
                                                                                                                           
    /*   child execs av[1] and writes into pipe         */                                                                  
                                                                                                                           
    close(thepipe[0]);      /* child doesn't read from pipe */                                                              
                                                                                                                           
    if ( dup2(thepipe[1], 1) == -1 )                                                                                        
        oops("could not redirect stdout", 4);                                                                              
                                                                                                                           
    close(thepipe[1]);      /* stdout is duped, close pipe  */                                                              
    execlp( av[1], av[1], NULL);                                                                                            
    oops(av[1], 5);                                                                                                        
}
sonic2000Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

lynxlupodianCommented:
Why 0? I don't think any process has that PID. And certainly no process has a negative PID. And afaik, you can't specify which PID to get when forking(may be just my inferiror knowledge).
0
sonic2000Author Commented:
it is possible to get a pid == -1 if the fork is unsuccessful (at least what is told by man fork)..
FYI, the above code is taken from a book and I am just wonder why when I swap child and parent, the result is so different.
0
lynxlupodianCommented:
-1 is not the PID, but the exit status code of fork. ;)

Well, doing something as "less | who" doesn't make sense from the start.
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

sonic2000Author Commented:
if ( (pid = fork()) == -1 )         /* get a proc   */
        oops("Cannot fork", 2);


pid == -1 if fork returns -1 (unsuccessful). Of course I know the result is the fork() :)

>>Well, doing something as "less | who" doesn't make sense from the start.
I did not say the code is doing that. I said "who | less" if you were to run the program plus read my question :)



Do you have better input?
0
lynxlupodianCommented:
>>I did not say the code is doing that. I said "who | less" if you were to run the program plus read my question :)
Didn't you ask why it's strange if you reverse them?

I'm guessing it's strange since only who generates output and only less can get piped input. So you are trying to get data from a silent command and give it to a deaf one. :D
0
sonic2000Author Commented:
sorry..
i am actually trying to ask why "who" has to be handled by child. Why can't parent handle it?
Is it because child will run first and so "who" should be handled by child?
0
lynxlupodianCommented:
yes. The first command in a pipe generates output which is then <i>piped</i> forward to the next commands which use that as their stdin. In your code it's child | parent, so who, the generator, should be first (child) and less, the manipulator, second (parent).

Any better? I hope so :)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
de2ZotjesCommented:
Can you tell what goes haywire ?

Does the program block, does it produce garbled output? What happens?

Because i feel (as you do) that this switch of roles of parent and child should be legal. The last comment from lynx.. is not pertinent to this situation, he is talking about shell piping, which is different from constructing  your own programmatic pipe. Even if the listener would run first, it would block on the attempt to read from the pipe thereby releasing the processor to execute the producer...
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux OS Dev

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.