6

I'm trying to use redirects in C to redirect input to one file and then set standard output back to print to the screen. Could someone tell me what's wrong with this code?

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char** argv) {
    //create file "test" if it doesn't exist and open for writing setting permissions to 777
    int file = open("test", O_CREAT | O_WRONLY, 0777);
    //create another file handle for output
    int current_out = dup(1);

    printf("this will be printed to the screen\n");

    if(dup2(file, 1) < 0) {
        fprintf(stderr, "couldn't redirect output\n");
        return 1;
    }

    printf("this will be printed to the file\n");

    if(dup2(current_out, file) < 0) {
        fprintf(stderr, "couldn't reset output\n");
        return 1;
    }

    printf("and this will be printed to the screen again\n");

    return 0;
}
David
  • 1,715
  • 5
  • 25
  • 40
  • 1
    There is a completely different way to solve this same problem here: http://stackoverflow.com/questions/584868/rerouting-stdin-and-stdout-from-c. – Sam Nov 26 '12 at 18:47

3 Answers3

4

One thing you'll have to make sure to do before that will work at all, is to call fflush(stdout); before switching the stdout file descriptor out from under it. What's probably happening is that the C standard library is buffering your output, unaware that you're shifting around the file descriptors underneath it. The data you write using printf() isn't actually sent to the underlying file descriptor until its buffer becomes full (or your program returns from main).

Insert the call like this:

    fflush(stdout);
    if(dup2(file, 1) < 0) {

before both calls to dup2().

Greg Hewgill
  • 828,234
  • 170
  • 1,097
  • 1,237
  • I don't think this was OP's problem here, but it's very good advice and should almost always be followed whenever you mix stdio with file descriptor io. – R.. GitHub STOP HELPING ICE Jul 24 '11 at 13:22
  • 1
    That's true, I actually didn't notice the incorrect file descriptor at first until somebody else mentioned it. When writing to a terminal, stdio output will probably be line buffered, so the code without `fflush()` is likely to work until the OP tries redirecting stdout to a file. – Greg Hewgill Jul 24 '11 at 19:24
3

Your second dup2 call is wrong, replace with:

if (dup2(current_out, 1) < 0) {
Mat
  • 188,820
  • 38
  • 367
  • 383
1

Just replace dup2(current_out, file) with dup2(current_out, 1), and things should work better.

Sander De Dycker
  • 15,403
  • 1
  • 31
  • 37