This is a buildup on an earlier question of mine: redirect stdout to a file
The situation is as follows: I am using an external library which provides vital functionality to my code, but which produces a large amount of logging information via printf (bad style, I know, but I can't change it, and I can't switch to another library).
I would like to redirect the output to a file, which I have managed to achieve with the help of the great StackOverflow community (see earlier link). Since then, the situation has gotten a little more complicated: Now I want to append my own logging information to the same output file, preferably using std::ofstream. The code is not and will never be parallelized, so concurrent write access is not a concern. However, please consider the following chunk of code:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// this is just a global "backup" of the stdout fd
// so that I can restore it after the function call
int stdoutfd = dup(fileno(stdout));
int stupid_library_function(){
// I can't change this function
printf("hello world!\n");
return 1;
}
int redirect_stdout(const char* fname, bool append){
// redirect printf to a file
fflush(stdout);
int newstdout = append ? open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) : open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
dup2(newstdout, fileno(stdout));
close(newstdout);
return fileno(stdout);
}
int restore_stdout(){
// restore the normal behaviour of printf
fflush(stdout);
dup2(stdoutfd, fileno(stdout));
return stdoutfd;
}
int main(){
// just to test if everything is normal
std::cout << "this is a normal printout" << std::endl;
// create my own output stream
std::ofstream outstream("log.txt");
// some of my own output
outstream << "calling stupid library function now" << "\n";
outstream.flush();
// redirect the output of the supid library function to the logfile
redirect_stdout("log.txt",true);
int val = stupid_library_function();
// neither of the following lines causes the output of the stupid library function to appear in the log file
fflush(stdout);
fsync(stdoutfd);
// restore the normal stdout
restore_stdout();
// some of my own output again
outstream << "done calling stupid library function, result was " << val << "\n";
outstream.flush();
// close my own output stream
outstream.close();
// just to test if everything is back to normal
std::cout << "this is (again) a normal printout" << std::endl;
return 1;
}
Compiling and running this code should give you a file "log.txt", which would contain the following lines
calling stupid library function now
done calling stupid library function, result was 1
Due to my naive understanding, the file should contain three lines, the output "hello world" from the library function call between the two you find above.
My first thought were that there was a problem with flushing the stdout buffer, so I tried using "fflush" and "fsync" (see above). However, neither of those seem to have any effect in this case.
Would anybody be willing to enlighten me and show me a way of how to obtain the output
calling stupid library function now
hello world
done calling stupid library function, result was 1
with the following constraints:
- the lines in the log file must be in the correct order
- printf and std::cout must be restored to default behaviour when the code is done
- the code of "stupid_library_function" must not be changed
- the output within "main" must still be using std::ofstream