Search code examples
c++cprogramming-languages

How this stdout redirection works?


Code below redirects stdout to a file fname & then redirects back to original stdout. It works fine for me. But I am not able to understand how it actually works. If anyone can help me understand I will appreiciate it.

    printf("\n This is console");
    fflush(stdout);
    fgetpos(stdout, &pos);
    fd = dup(fileno(stdout));
    freopen(fname, "a+", stdout);   

    printf("inside file op");  

    fflush(stdout);
    dup2(fd,fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);
    printf("\nBack to Console");

Solution

  • Let's go through it line by line. The first line prints something to stdout:

    printf("\n This is console");
    

    Then it flushes stdout so all the remaining data in the buffer gets sent to stdout and won't get mixed up with the file data:

    fflush(stdout);
    

    Now we store the current position of ourselves in stdout because otherwise if stdout was already directed to a file, we might (?) overwrite earlier parts of it.

    fgetpos(stdout, &pos);
    

    Now we clone the file descriptor of what's currently stdout. Since we're about to change where stdout points to, we need to keep a copy of the original:

    fd = dup(fileno(stdout));
    

    Now that we have everything preserved, we can reopen stdout as the file:

    freopen(fname, "a+", stdout);
    

    At this point, stdout has been redirected to the file. We can now print to it:

    printf("inside file op");  
    

    Now we're done printing to the file. We need to flush stdout (now the file) so it doesn't get mixed up with the normal stdout data:

    fflush(stdout);
    

    After that, we clone the original stdout file descriptor over the current stdout descriptor.

    dup2(fd,fileno(stdout));
    

    The cloned one can be closed now:

    close(fd);
    

    I'm not quite sure why this is here but this clears any errors that occurred writing to the file:

    clearerr(stdout);
    

    Now we restore our position in stdout. Again, as far as I know, this is only useful if it was originally redirected to a file:

    fsetpos(stdout, &pos);
    

    Now we're back to the original stdout, so we can print again:

    printf("\nBack to Console");