edit: using fopen to create the capture file. Then fileno
to get the fd of the capture file. Then use fd as input to dup2
to redirect stdout to this capture file. Anyway, get same results. fflush
does not flush and save the captured output.
I want to redirect stdout to a file. Capture some output. Then terminate that redirect and resume output to stdout. How to do this?
freopen
handled the redirect. But I read I cannot resume output to stdout. So I am using dup
and dup2
.
Problem with dup2
is once I shutdown the redirect all the output goes to stdout. The output both before and after the redirect.
I have tried to flush the redirect captured output using fsync
. But that does not work. When I use gdb
to step through the code nothing is written to the redirected output file until the program actually ends.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <time.h>
#include <libgen.h>
#include <fcntl.h>
int main()
{
// open() returns a file descriptor file_desc to a
// the file "dup.txt" here"
FILE *fp1 = fopen( "dup.txt", "w");
int fd = fileno( fp1 ) ;
if (fd < 0)
{
char errtxt[256];
strcpy( errtxt, strerror(errno)) ;
printf("Error opening the file. %s\n", errtxt );
}
int saved_stdout = dup(STDOUT_FILENO);
dup2( fd, STDOUT_FILENO);
printf("line 1\n") ;
fflush(fp1) ;
printf("line 2\n") ;
fflush(fp1);
fclose(fp1) ;
// revert back to stdout
dup2(saved_stdout, STDOUT_FILENO);
close( saved_stdout ) ;
printf("line 3\n");
printf("line 4\n");
return 0;
}
Very confusing. If I insert a return 0
after the output of the first two lines, that output shows up in the output file. But running the code which resumes output to stdout causes all the output lines to appear on the console and there is nothing in the output file.
CodePudding user response:
Here:
printf("line 1\n") ; fflush(fp1) ;
you are writing to stdout
, but flushing an altogether different stream. That the two are both connected to the same file descriptor is irrelevant -- each stream has its own, separate buffer. Instead, flush the stream to which you have actually written:
printf("line 1\n");
fflush(stdout);
etc.
As a result of that error, yes, the data you write while the redirect is in effect are not flushed to the target file. You then restore the original stdout
before the data are flushed at program exit.
With that in mind, observe that you have confused matters by using fopen()
to open a stream bound to the file when all you ever needed or wanted was the file descriptor. open()
would be a better choice here:
int fd = open("dup.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666) ;
Now there is no second stream to complicate the situation.
As a separate matter, note also that this ...
char errtxt[256]; strcpy( errtxt, strerror(errno)) ; printf("Error opening the file. %s\n", errtxt );
... comes pretty close to duplicating the behavior of the standard perror()
function, except that it writes to stdout
instead of stderr
(which is a flaw).