There are several ways of redirecting the output of a child process:
- using
freopen(3)
- using
dup(3)
- using
popen(3)
- ...
What should one pick if all is wanted is to execute a child process and have it output saved in a given file, pretty much like the ls > files.txt
works?
What is normally used by shells?
I would expect to find
dup2()
used mainly.Neither
popen()
norfreopen()
is designed to handle redirections such as3>&7
. Up to a point,dup()
could be used, but the3>&7
example shows wheredup()
starts to creak; you'd have to ensure that file descriptors 4, 5, and 6 are open (and 7 is not) before it would handle whatdup2()
would do without fuss.You can discover what your favorite shell uses by
strace(1)
ing your shell.In one terminal:
In another terminal:
In the first terminal again:
In the second terminal,
^C
yourstrace(1)
command and then edit the/tmp/shell
output file to see what system calls it made to do the redirection.freopen(3)
manipulates the C standard IOFILE*
pointers. All this will be thrown away on the other side of theexecve(2)
call, because it is maintained in user memory. You could use this after theexecve(2)
call, but that would be awkward to use generically.popen(3)
opens a single unidirectionalpipe(7)
. This is useful, but extremely limited -- you get either the standard output descriptor or the standard input descriptor. This would fail for something likels | grep foo | sort
where both input and output must be redirected. So this is a poor choice.dup2(2)
will manage file descriptors -- a kernel-implemented resource -- so it will persist acrossexecve(2)
calls and you can set up as many file descriptors as you need, which is nice forls > /tmp/output 2> /tmp/error
or handling both input and output:ls | sort | uniq
.There is another mechanism:
pty(7)
handling. Theforkpty(3)
,openpty(3)
, functions can manage a new pseudo-terminal device created specifically to handle another program. The Advanced Programming in the Unix Environment, 2nd edition book has a very nicepty
example program in its source code, though if you're having trouble understanding why this would be useful, take a look at thescript(1)
program -- it creates a new pseudo-terminal and uses it to record all input and output to and from programs and stores the transcript to a file for later playback or documentation. You can also use it to script actions in interactive programs, similar toexpect(1)
.