Hi there,
I read about freopen
to redirect all printf
to a file, but I would like the output to be printed on the screen as well. Is there an easy way to redirect the printfs to a file and get the cmd line output?
Thanks!
Hi there,
I read about freopen
to redirect all printf
to a file, but I would like the output to be printed on the screen as well. Is there an easy way to redirect the printfs to a file and get the cmd line output?
Thanks!
From outside the program, use "tee":
# echo foo | tee foo.txt
foo
# cat foo.txt
foo
In fact, you could popen() a channel to a tee that writes the file, though that's system-heavy. Something to this effect:
FILE *stream_to_write_to = popen( "tee filename.txt" );
fprintf( stream_to_write_to, "goes to filename.txt and stdout\n" );
I'm curious to see if there's a from-C quick way of doing this, because at some level, this involves copying data. It's easy to get two filehandles to write to the same place, use dup() or the like, but the opposite is more tricky. It might involve pushing a module (the common example is "connld" onto a stream), though honestly I've never seen this used, so I'd love to see a working code sample myself.
Best reference I can give is "Advanced Programming in the UNIX Environment" by Stevens.
Update:
To speak to R's comment below, the above solution is a slightly heavier version of just fork/exec-ing and redirecting the child's handle someplace else. Both will solve the problem, though I prefer the above because it's easier to clean up, but honestly, both solutions are pretty heavy. Fork() is no lightweight function. If the spirit of the question is to do so without fork/exec, then I'm not sure, I'd love to know, too. If fork/exec is okay, then directly using it or using popen() will hack it.
freopen
is not a good idea for redirecting stdout. It will not necessarily reuse the same file descriptor number so child processes may not inherit the new stdout (or may end up with no stdout at all). It's better to use open
and then dup2
or close(0)
then open
to create a new target for stdout.
Another alternative is to write a function that works like printf
, but directs the output to two different places. For instance:
#include <stdio.h>
#include <stdarg.h>
void printf2(FILE *fp, char *format, ...)
{
va_list ap;
va_list ap2;
va_start(ap, format);
va_copy(ap2, ap);
vfprintf(fp, format, ap);
va_end(ap);
vprintf(format, ap2);
va_end(ap2);
}
You can then call printf2
the same way you'd call fprintf
, and the output will go to both the passed-in FILE
pointer and to stdout:
FILE *fp = fopen("/tmp/foo", "w");
printf2(fp, "This is a test.\n");
This approach does not use subprocesses or pipes, and it can be generalized to multiple file pointers, if necessary.