29

I am working with a multi-thread program.

First I redirect my stdout to a certain file. No problem there (I used dup2(fd, 1) where fd is the file descriptor for the file).

Afterwards, I need to redirect my stdout to the terminal again.

My first approach:

      /*Declaration*/
      fpost_t  stream_sdout;
      /*code*/
      if ( fgetpos( stdout, &stream_sdout) == -1 )
          perror(Error:);

It says illegal seek.
No idea why this is happening.
But if I get this to work, then I only need to use fsetpos(stdout, &stream_stdout) and it should work.

My second idea, was to to copy the stdout using dup2(stdout, 4) to the file descriptor table, at position 4. But that ain't working either.

How can I switch the standard output back to its original destination (terminal, pipe, file, whatever)?

8
  • I have a feeling that trying to move stdout around like this is probably a bad idea -- what position exactly should the terminal report in fgetpos()? Why not simply open a file and output to it using fwrite() or fprintf() or write() and output to the terminal via /dev/tty when you need it?
    – sarnold
    Commented Jun 14, 2012 at 22:30
  • 1
    @sarnold: probably because the program has libraries or other unalterable code which are hardwired to stdout.
    – wallyk
    Commented Jun 14, 2012 at 22:31
  • @sarnold i actually didnt give it thought to that posibility. Let me check quickly. Commented Jun 14, 2012 at 22:37
  • I don't have enough information to post a good answer, so I'm commenting instead. In Windows, you can re-attach the console. I'd look at any Win32 SDK documentation. It's not hard; I just can't remember how to do it. Commented Jun 14, 2012 at 22:49
  • @sarnold thanks for the advice! That was much easier. I was able to make it work to perfection. I still have the doubt if restoring the std is possible, but your solution got me out of a tight spot. Thanks! Commented Jun 14, 2012 at 22:54

3 Answers 3

53
#include <unistd.h>

...

int saved_stdout;

...

/* Save current stdout for use later */
saved_stdout = dup(1);
dup2(my_temporary_stdout_fd, 1);

... do some work on your new stdout ...

/* Restore stdout */
dup2(saved_stdout, 1);
close(saved_stdout);
2
  • This really helped me out a lot. I was wondering though what is the function of close(saved_stdout)? I've used close for closing files but I am not yet familiar with how the whole dup function process works. Commented Apr 13, 2014 at 19:22
  • 4
    @ThinkBonobo, saved_stdout is a duplicate (hence, dup()) of the original file descriptor for the original file underlying the program's stdout. When is it again duplicated back to (dup2()) stdout (file descriptor no. 1), the program has two copies/handles/descriptors for the same underlying file. There's no need for this once the output redirection is finished (and it might confound resource limits or assumptions about file locks, etc.), so good practice is to dismiss the resource when no longer needed.
    – pilcrow
    Commented Apr 15, 2014 at 15:44
13

Before you do the dup2(fd, STDOUT_FILENO), you should save the current open file descriptor for standard output by doing int saved_stdout = dup(STDOUT_FILENO); (letting dup() choose an available file descriptor number for you). Then, after you've finished with the output redirected to a file, you can do dup2(saved_stdout, STDOUT_FILENO) to restore standard output to where it was before you started all this (and you should close saved_stdout too).

You do need to worry about flushing standard I/O streams (fflush(stdout)) at appropriate times as you mess around with this. That means 'before you switch stdout over'.

0
0

If the program runs on a Linux environment, you can freopen ("/dev/stdout", "a", stdout).

But if you know that stdout was the terminal, freopen ("/dev/tty", "a", stdout) or the equivalent for other OSs—even Windows.

3
  • 1
    When the dup2() works, /dev/stdout should refer to the file. So you've switched the output from the file to the file, I believe. Commented Jun 14, 2012 at 23:02
  • @JonathanLeffler: If he is changing the fds around, that would be true. It is far from apparent from his description that is what is happening. It seems he might be changing around the FILE connections instead.
    – wallyk
    Commented Jun 14, 2012 at 23:11
  • Since he mentions using dup2() to switch the standard output, it seems to me he is messing with file descriptors to start with. The code to reset things in the question is weird beyond rescue; a rewrite is in order. But that's what the answers are supposed to be about, of course. Commented Jun 14, 2012 at 23:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.