Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-opening stdout and stdin file descriptors after closing them

Tags:

c

linux

unix

I'm writing a function, which, given an argument, will either redirect the stdout to a file or read the stdin from a file. To do this I close the file descriptor associated with the stdout or stdin, so that when I open the file it opens under the descriptor that I just closed. This works, but the problem is that once this is done, I need to restore the stdout and stdin to what they should really be.

What I can do for stdout is open("/dev/tty",O_WRONLY); But I'm not sure why this works, and more importantly I don't know of an equivalent statement for stdin.

So I have, for stdout

close(1); if (creat(filePath, O_RDWR) == -1) {     exit(1); } 

and for stdin

close(0); if (open(filePath, O_RDONLY) == -1) {     exit(1); } 
like image 209
RegisteredUser Avatar asked Jan 31 '12 17:01

RegisteredUser


People also ask

Does stdin need to be opened?

At program start-up, three streams shall be predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output).

Are stdout files descriptors available?

On program startup, the integer file descriptors associated with the streams stdin, stdout, and stderr are 0, 1, and 2, respectively. The preprocessor symbols STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO are defined with these values in <unistd. h>.


1 Answers

You should use dup() and dup2() to clone a file descriptor.

int stdin_copy = dup(0); int stdout_copy = dup(1); close(0); close(1);  int file1 = open(...); int file2 = open(...);  < do your work. file1 and file2 must be 0 and 1, because open always returns lowest unused fd >  close(file1); close(file2); dup2(stdin_copy, 0); dup2(stdout_copy, 1); close(stdin_copy); close(stdout_copy); 

However, there's a minor detail you might want to be careful with (from man dup):

The two descriptors do not share file descriptor flags (the close-on-execflag). The close-on-exec flag (FD_CLOEXEC; see fcntl(2)) for the duplicate descriptor is off.

If this is a problem, you might have to restore the close-on-exec flag, possibly using dup3() instead of dup2() to avoid race conditions.

Also, be aware that if your program is multi-threaded, other threads may accidentally write/read to your remapped stdin/stdout.

like image 114
Ambroz Bizjak Avatar answered Oct 13 '22 11:10

Ambroz Bizjak