cpipeforkdup2dup

How to use dup2 to redirect stdin and stdout to pipe file descriptors?


I was trying to fork a process and redirect stdout of the parent to the writing end of the pipe and stdin of the child to the reading end of the pipe. The child is supposed to read integers until the parent prints zero. the parent prints from 1 to 3 and then prints 0. Both the parent and the child prints the time when they start and when they finish. since the parent can't print to stdout it sends it's starting and finishing time to the child and the child prints both its starting time and finishing time and parents starting time and finishing time. I could've used dup and redirected stdout to another file descriptor but I chose to make it simple. The program is very simple but the output that I get doesn't make scene.

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main() 
{ 
    int fd[2];
    int p = pipe(fd);
    int ch = fork();

    if (ch)
    {
        // Parent - Counts from 1 to 3
        int dp = dup2(fd[1], 1);
        printf("Cnt_Started_at_%d\n", time(NULL));
        for (int i = 0; i <= 3; i++)
        {
            printf("Parent %d\n", i);
            sleep(1);
        }
        printf("0\n");
        printf("Cnt_Finished_at_%d\n", time(NULL));
    }
    else 
    {
        // Child - Terminated by 0
        int dp = dup2(fd[0], 0);
        printf("Trm_Started_at_%d\n", time(NULL));
        char buffer[100];
        scanf("%s", buffer);
        printf("%s\n", buffer);

        int i; 
        while (scanf("Parent %d", &i) && i)
            printf("Recieved: %d\n", i);

        scanf("%s", buffer);
        printf("%s\n", buffer);
        printf("Trm_Finished_at_%d\n", time(NULL));
    }
}

Output:

Trm_Started_at_1578295974
Cnt_Started_at_1578295974
Parent
Trm_Finished_at_1578295978

Solution

  • The root issue is the usage of 'scanf %s' to read messages. Recall that '%s' will stop reading when it encounter white space, and will put the white space back into the buffer.

    The initial message from the parent is 'Cnt_Started_at_1234\n'. This child process will read the token, but will leave the trailing '\n' in the buffer.

    Next the parent will send 'Parent 0\n'. The Child will attempt to parse this is scanf("Parent %d", &i) && i). Two issues here:

    Possible solution: Allow the scanf to skip of spaces, and eliminate the condition on i

        while (scanf(" Parent %d", &i) == 1 )
                printf("Recieved: %d\n", i);