How this stdout redirection works? - c++

Code below redirects stdout to a file fname & then redirects back to original stdout. It works fine for me.
But I am not able to understand how it actually works. If anyone can help me understand I will appreiciate it.
printf("\n This is console");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen(fname, "a+", stdout);
printf("inside file op");
fflush(stdout);
dup2(fd,fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos);
printf("\nBack to Console");

Let's go through it line by line. The first line prints something to stdout:
printf("\n This is console");
Then it flushes stdout so all the remaining data in the buffer gets sent to stdout and won't get mixed up with the file data:
fflush(stdout);
Now we store the current position of ourselves in stdout because otherwise if stdout was already directed to a file, we might (?) overwrite earlier parts of it.
fgetpos(stdout, &pos);
Now we clone the file descriptor of what's currently stdout. Since we're about to change where stdout points to, we need to keep a copy of the original:
fd = dup(fileno(stdout));
Now that we have everything preserved, we can reopen stdout as the file:
freopen(fname, "a+", stdout);
At this point, stdout has been redirected to the file. We can now print to it:
printf("inside file op");
Now we're done printing to the file. We need to flush stdout (now the file) so it doesn't get mixed up with the normal stdout data:
fflush(stdout);
After that, we clone the original stdout file descriptor over the current stdout descriptor.
dup2(fd,fileno(stdout));
The cloned one can be closed now:
close(fd);
I'm not quite sure why this is here but this clears any errors that occurred writing to the file:
clearerr(stdout);
Now we restore our position in stdout. Again, as far as I know, this is only useful if it was originally redirected to a file:
fsetpos(stdout, &pos);
Now we're back to the original stdout, so we can print again:
printf("\nBack to Console");

Related

fprintf function not working but it returns positive number

I'm using fprintf in the following way. Everything seems to be ok but fprintf doesn't print to my file at all!
fprintf(pFile, "%s\n", "print");
Something that is strange is that fprintf returns OK. it returns 6 in the above code, but not printing to file!
The file is created successfully but is empty.
changing it to printf is printing and OK too.
fprintf and the other stdio output functions are buffered, which means that the output is first stored in memory, and not actually printed until later. When printing to the screen using standard output, each new line flushes the buffer, so with printf you would see the output immediately, but when printing to a file the buffer won't be flushed until you have written (for example) 4096 bytes. You can add fflush(pFile); to flush the buffer, if you for some reason need the output to appear on the file quickly.
The buffer is also flushed when calling fclose, or closing the file implicitly by properly exiting the program, but if the program keeps running without closing the file, or if it crashes, you will need fflush to see the output on the file.

get failed output back

I'm trying to run a script and output the result in the console. It works, but there is a
small problem i'm facing right now. If the "script" file is writed/coded wrong i get as output something like:
syntax error, unexpected $undefined, expecting $end puts
which is very good that it tells me somehting is wrong with the code inside the script file, but in my code line:
printf("%s", path);
it dosent print that to me and i want it to print it so i can display it on the screen. Please help me out
fp = popen("our script...is here", "r");
if (fp == NULL)
/* Handle error */;
while (fgets(path, PATH_MAX, fp) != NULL)
printf("%s", path);
status = pclose(fp);
Ps: just to make it more clear i'm using xcode and dont mind the code in C or C++
By default fgets() reads only from stdout of the stream. To capture stderr, you can simply redirect it to stdout:
fp = popen("./script 2>&1", "r");
Now both the stdout and stderr will go stdout which your C code can read from.
Note that once you have redirected as above there's no way to differentiate stdout and stderr.
You have to care about the stderr - popen() handled only stdout:
Conversely, reading from a "popened" stream reads the command's standard output,
The shell error will be printed to stderr - which popen() does not handle.

using std::freopen to redirect stderr c++

I want to redirect all stderr to a file, which is also being used by my logger for the entire time the application (game) is running.
The following redirects it away from the console, but it never appears in my file, and using fclose after the game loop is over doesn't actually do anything, where it normally should.
freopen(Logger::logFile.c_str(),"a",stderr);
Any help would be great on how to get stderr to output to the text file, in a game loop.
We might here be playing with undefined behavior... because you must not use freopen to redirect various things to the same file.
In the below example, depending on what file you close, you will write differently:
#include <stdio.h>
int main ()
{
freopen ("myfile.txt","w",stdout);
printf (" This sentence is redirected to a file.");
// fclose (stdout);
freopen ("myfile.txt","w",stderr);
fprintf (stderr, "This ERRORis redirected to a file.");
//fclose (stderr);
fclose (stdout);
return 0;
}
Here you write the error before the sentence:
This ERRORis redirected to a file.sentence is redirected to a file.
Not great. I suggest you let the OS do this redirection to same file work for you, e.g. in Unix / Linux:
./myprog.sh 2>&1

About the read() in unistd.h (C++)

all, I am designing a Key-Value server, and when I wrote the client, and I found a really strange thing,see the simplified code:
while(1)
{
printf("->:");
read(STDIN_FILENO, buf, sizeof(buf));
write(client_sock, buf, sizeof(buf));
int m = read(client_sock, buf, sizeof(buf));
buf[m] = '\0';
printf("%s", buf);
}
when I run the program, it first ask for input, so I input something, but nothing happen!
(the server runs well, and it well echo something, when I use other client)
then I change the code only one line:
printf("\n->:");
then it runs well! why? why "\n" can change the output? I guess it maybe the read() , but I can't explain it
printf(3) is part of the C standard IO library, which performs internal buffering to provide performance improvements.
There are three types of buffering: none, line, and block.
Which buffering is applied is determined in part by whether the descriptor being written to is 2 or not, and if it is connected to a terminal. (See isatty(3).)
If the printing is done to stderr (2) then no buffering is done.
If the printing is done to any other descriptor, then the behavior changes if it is a terminal or not: if output is a terminal, then the output is line buffered. If the output is not a terminal (file, pipe, socket, etc.) then the output is block buffered.
When line buffered, it waits for the \n before printing anything. (Or if you write enough to overflow the internal buffers before sending a \n.)
What I'd recommend instead is the following:
printf("->:");
fflush(stdout);
read(STDIN_FILENO, buf, sizeof(buf));
/* ... */
printf("%s\n", buf);
It's a small change; you won't get a pointless empty line at program start, and the prompt should show up .. promptly.
You can use the setvbuf(3) function to change the buffering for your stream once, at start up, and never need to flush it again, if you would rather.
int err = setvbuf(stdout, NULL, _IONBF, 0);
/* check err */
Standard output is line-buffered by default. If you don't write a complete line, the output will be held in the buffer until you do. You can use fflush to flush the stream or setbuf to change the buffering mode.

Writing ALL program output to a txt file in C++

I need to write all my program output to a text file. I believe it's done this way,
sOutFile << stdout;
where sOutFile is the ofstream object that creates the file like this:
sOutFile("CreateAFile.txt" ); // CreateAFile.txt is created.
When I insert the stdout into the sOutFile object, I get some code which seems to resemble octal [hexadecimal] code or an address of some kind in the text file that I created.
0x77c5fca0
But what's confusing to me is that in my program I use cout several times. Mostly just literal statement. If I'm not mistaken that is the program output.
If this code is an address, would it contain all of my output? Could I read it back in to the program and find out that way?
What can I do to get ALL of my program output written to a text file?
If your program already uses cout/printf and you want to send EVERYTHING you currently output to a file, you could simply redirect stdout to point to a file before your existing calls:
http://support.microsoft.com/kb/58667
Relevant Code:
freopen( "file.txt", "w", stdout );
cout << "hello file world\n"; // goes to file.txt
freopen("CON", "w", stdout);
printf("Hello again, console\n"); // redirected back to the console
Alternatively if you just want Some things to be printed to a file, you just want a regular file output stream: http://www.cplusplus.com/doc/tutorial/files.html
Relevant Code:
ofstream myfile;
myfile.open("file.txt");
myfile << "Hello file world.\n";
printf("Hello console.\n");
myfile.close();
EDIT to aggregate answers from John T and Brian Bondy:
Finally, if you're running it from the commandline, you can just redirect the output as everyone else mentioned by using the redirect operator ">" or append ">>":
myProg > stdout.txt 2> stderr.txt
This is a duplicate of: this question
You can redirect stdout, stderr and stdin using std::freopen.
From the above link:
/* freopen example: redirecting stdout */
#include <stdio.h>
int main ()
{
freopen ("myfile.txt","w",stdout);
printf ("This sentence is redirected to a file.");
fclose (stdout);
return 0;
}
You can also run your program via command prompt like so:
a.exe > stdout.txt 2> stderr.txt
If you want all output in a text file you don't need to code anything extra.
from the command line:
program > output.txt
If you only wish to redirect certain output you can use ostream as dirkgently suggested.
Then you cannot use std::cout anywhere else to print stuff from your program. Change std::cout to a std::ostream and then pass your file or std::cout as required.
sOutFile << stdout;
in C "stdout" is defined as a FILE* variable. It's just a pointer. Outputing it to a file just writes the value of the pointer, in your case: 0x77c5fca0 to the file.
If you want to direct your output to a file either write it the a file in the first place or redirect the output of your program to a file using the command line.