Thread: Exec and Pipe problem

  1. #1
    Registered User
    Join Date
    Sep 2010
    Posts
    6

    Question Exec and Pipe problem

    Hey guys. I have to make two c programs, parent.c and child.c. Basically the parent will fork a new process for every child it needs to make, create a pipe and connect the stdio input or output of the new process to the pipe (which is also connected to the parent) and call an exec function for child.c. I get that when you call exec the stdin and stdout are inherited from the process but I'm unsure how to actually get the parent process and the child.c to communicate through the pipe. I've looked around for examples of this but I cant find exactly what I'm looking for.

    If you could just show me how to send a string (char []) from the parent to the the child.c process that would be great. I'm not sure exactly what I'm doing wrong (or right for that matter lol).

    Code:
    #define __EXTENSIONS__
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #define COMM_TERM "OUT"
    #define COMM_CONT "OVER"
    #define MAX_BUFFER_SIZE 128
    
    
    int main(void)
    {
        int pipe_one[2];
        int status;
        int wait_ret;
        char buffer[MAX_BUFFER_SIZE];
        
        
        /* Create a pipe. */
        if(pipe(pipe_one) == -1)
        {
            perror("ERROR");
            exit(EXIT_FAILURE);
        }
        
        
        /* Create first child process. */
        if(fork() == 0)
        {
            /* first child process */
            printf("First child process with pid %d alive.\n", (int)getpid());
    
            /* Close unused pipe */
            close(pipe_one[1]);
            
            /* Attach Child 1 stdin to Parent stdout */
            dup2(pipe_one[0], 1);
            
            /* Exectute Child program */
            execlp("./child", "child" ,"-f", NULL);
    
        }
        
        close(pipe_one[0]);
        
        write(pipe_one[1], "You Beauty!!!", 127);
        
      return EXIT_SUCCESS;
    }

    -child.c


    [code]
    #define __EXTENSIONS__
    #include <unistd.h>
    #include <strings.h>
    #include <stdlib.h>
    #include <stdio.h>

    int
    main(int argc, char *argv[])
    {
    int launchChild, flags, childOnly, opt;
    char *pipeName;
    int pipeLen, pfind;
    char buffer[128];

    while(1)
    {
    read(buffer, 127, stdin);

    if(strcmp(buffer, "EXIT") == 0)
    {
    close(0);
    exit(EXIT_SUCCESS);
    }
    if(strcmp(buffer, "You Beauty!!!") == 0)
    {
    printf("%s\n", buffer);
    }
    }

    exit(EXIT_SUCCESS);
    }

    [\code]

    Thanks for any help
    Last edited by Matteaus; 09-06-2010 at 01:37 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Your compiler should be complaining when you build your child program. The following:
    Code:
    read(buffer, 127, stdin);
    requires a diagnostic, because it's not using read() correctly at all. First off, read() is not part of the standard I/O functions, so it won't use stdin (which is a FILE*); it uses file descriptors. Second, not one of the arguments to read() is in the right place, even if you change stdin.

    You also have to be careful when you're using read() like this, because it won't necessarily create a string (meaning passing what you get to printf() or strcmp() can be a bad idea). For a beginner program, where you know you'll always send a full string, it's not a huge deal, but it's something to have in the back of your head.

    Now, on to the parent. The fundamental problem is in your usage of dup2(). When you do this:
    Code:
    dup2(pipe_one[0], 1);
    this will close standard output (which is file descriptor 1), and reopen it as a copy of pipe_one[0], which is the read end of the pipe. There is a mismatch here, since standard output is for writing.

    What your goal is, here, is to get your child to read from standard input, but have that standard input come from your parent. So you want to manipulate the child's standard input, not its standard output. Thus you should have dup2() fiddle around with file descriptor 0, or more verbosely:
    Code:
    dup2(pipe_one[0], STDIN_FILENO);
    Now whenever standard input is read in the child, it will read from the pipe. On the parent's side, you won't be writing to standard output, but instead, to a pipe (you could call dup2() in the parent to reopen standard output, but there's no reason to here).

    So then we come to the write:
    Code:
    write(pipe_one[1], "You Beauty!!!", 127);
    You're writing to the correct place, but you're writing too much! You're telling write() that you have 127 bytes to send, but you don't: you only have 14 (don't forget the null character at the end of a string).

    As it stands, your child will loop infinitely with this code since EXIT is never being sent, and the return value of read() is not being checked. For robust code, you'll want to check the return value of most functions that have one. In this case, read() might return 0 or -1, in which case you'll probably want to stop reading.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 10-14-2009, 04:44 PM
  2. Replies: 3
    Last Post: 06-02-2009, 06:13 PM
  3. Unix pipe simulation
    By TaviO! in forum C Programming
    Replies: 4
    Last Post: 03-19-2008, 12:47 AM
  4. exec and pipes
    By zedoo in forum Linux Programming
    Replies: 5
    Last Post: 10-07-2005, 11:12 AM
  5. exec with linux pipe command
    By rotis23 in forum C Programming
    Replies: 4
    Last Post: 08-22-2002, 08:34 AM