Search code examples
cioposix

Redirecting stdout to stdin in POSIX C


I am trying to write a program that redirects stdout into stdin, mostly to better understand how dup2() works. I tried writing a simple program that would make it so that if you printf() something, you can later scanf() it back, but didn't manage to get it to work. First I tried just using dup2(0, 1), thinking it would redirect stdout (1) to stdin (0). This didn't work. I thought that since one is used for input and the other for output they might not be compatible, so I tried using a pipe to do this, like so:

#include <stdio.h>
#include <unistd.h>
int main() {
    int pipe_desc[2];
    pipe(pipe_desc);
    dup2(pipe_desc[0], 0);
    dup2(pipe_desc[1], 1);
    printf("foo");
    char bar[20];
    scanf("%s", bar);
    fprintf(stderr, "%s", bar);
}

However, now even though printf, as I understand it, was supposed to put "foo" into the pipe, when I call scanf, the program just hangs there, and reads neither from stdin, nor from the pipe. What is wrong? What exactly happens in this code? Can such redirection be done without pipes (or any other helper structures for that matter)?


Solution

  • How your works, explanation is there in the code.

    #include <stdio.h>
    #include <unistd.h>
    int main() {
            int pipe_desc[2];
            pipe(pipe_desc);
            printf("pid = %d \n",getpid());
            /* above statement creates 2 descriptors 3 & 4. 3 is for read and 4 is for write**/
            dup2(pipe_desc[0], 0);
            /** 3 is duplicates with 0(stdin) i.e if you try to do scanf, it won't scan from keyboard, it will scan from pipe(read end, for that make sure something should be there in pipe  **/
            dup2(pipe_desc[1], 1);
            /** 4 is duplicates with 1 (stdout) i.e if you try to write onto screen, it won't. It will try into pipe write end **/
            /** SO TILL NOW FD DETAILS
                    0,3 --> PIPE_DESC[0]
                    1,4 --> PIPE_DESC[1] 
            **/
            #if 1
            fflush(stdout);
            printf("foo\n");//it won't print 
            char bar[20];
            scanf("%s", bar);//it won't scan bcz 0 is poiting to pipe_desc[0]
            #endif
            /** YOU CAN CHECK USING OTHER TERMINAL "ls -l /proc/pid/fd/" **/
    
            fprintf(stderr, "%s", bar);// fd 2 is still available.So foo gets printed on screen
    }
    

    open another terminal while above program is running, view the fd details using

    root@xyz-PC:/home/achal/s_flow/cpp# ls -l /proc/4503/fd
    total 0
    lr-x------ 1 root root 64 Jan 15 16:45 0 -> pipe:[782489]
    l-wx------ 1 root root 64 Jan 15 16:45 1 -> pipe:[782489]
    lrwx------ 1 root root 64 Jan 15 16:45 2 -> /dev/pts/9
    lr-x------ 1 root root 64 Jan 15 16:45 3 -> pipe:[782489]
    l-wx------ 1 root root 64 Jan 15 16:45 4 -> pipe:[782489]