29

Within my C program, I’d like to temporarly redirect stdout to /dev/null (for example). Then, after writing to /dev/null, I’d like to restore stdout. How do I manage this?

ib.
  • 27,830
  • 11
  • 80
  • 100
Frank
  • 18,432
  • 9
  • 30
  • 30

1 Answers1

58

On POSIX systems, you can do it as follows:

int bak, new;

fflush(stdout);
bak = dup(1);
new = open("/dev/null", O_WRONLY);
dup2(new, 1);
close(new);

/* your code here ... */

fflush(stdout);
dup2(bak, 1);
close(bak);

What you want is not possible in further generality.

Any solution using freopen is wrong, as it does not allow you to restore the original stdout. Any solution by assignment to stdout is wrong, as stdout is not an lvalue (it's a macro that expands to an expression of type FILE *).

ib.
  • 27,830
  • 11
  • 80
  • 100
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Don't use dup2. Use close(new) and then dup(1); dup() ensures you'll get the correct descriptor. `If newfd was open, any errors that would have been reported at close() time, are lost. A careful programmer will not use dup2 without closing newfd first. ` – Lilian A. Moraru Mar 11 '12 at 21:30
  • 13
    @MoraruLilian: I used `dup2` very intentionally. Your comment has the arguments all mixed up versus my code, so I can't be sure what your point is, but any solution without `dup2` has **dangerous race conditions**. The point of `dup2(x,y)` is to replace `y` **atomically** with a copy of `x`. – R.. GitHub STOP HELPING ICE Mar 12 '12 at 03:04
  • If you are in search of a way to write to a new file and you're like me and haven't memorized all the args to `open`, change the `open` line to `newFd = open(filename, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );` – Mark Lakata Jun 03 '20 at 01:52