get failed output back - c++

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.

Related

How do I get the content of llvm::MemoryBuffer when reading STDIN?

I am using llvm::MemoryBuffer::getFileOrSTDIN("-") and, according to the specification, it should Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
Now, in the following context:
auto Source = llvm::MemoryBuffer::getFileOrSTDIN(File);
if (std::error_code err = Source.getError()) {
llvm::errs() << err.message();
} else{
someFunction(std::move(*Source), File, makeOutputWriter(Format, llvm::outs()),
IdentifiersOnly, DumpAST);
}
it blocks on the first line (when File == "-"); as expected as the STDIN never closes.
When a special *char appears in STDIN, let's say <END_CHAR>, I know that I am finished reading for a given task. How could I close the STDIN in this situations and move on to someFunction ?
Thanks,
You can always close the stdin file descriptor using close, i.e. close(0). If you check llvm::MemoryBuffer's source, you'll see that getFileOrSTDIN() basically boils down to a call to llvm::MemoryBuffer::getMemoryBufferForStream() with the first argument (the file descriptor) set to 0.
Also, see this SO answer.
The special character to close the standard input is ctrl-d (in *nix at least) on the command line (have a look here).

Stdout being not read using "popen" and "read" functions

I have a c++ code that is trying to run losetup /dev/loop* and parse what is spitting back at the terminal.
The code is as so
char cmd[32] = {0, };
sprintf(cmd, "losetup /dev/loop%d", i);
FILE *fp;
fp = popen(cmd,"r");
char buf[1024];
read(fileno(fp), buf, 123);
printf("After read: %s\n", buf);
Two different things happen.
When the loop device is set up, the output is like so:
After read: /dev/loop0: [0802] ...Remaining ommitted
which is what I want and expect.
However, when the loop device is not properly set up, the output is like so:
loop: can't get info on device /dev/loop1: No such device or address
After read:
As you can see, "buf" is NULL, and the stdout that should be inside "buf" just printed itself in the terminal. I need to read the output not only when the loop device is set up but also when it isn't. So, can someone explain how to fix this so I can store stdout of both cases?
PS. I've tried "dup2" with "pipe", "fgets", and "getline", and they have all failed similarly.
Pipes only go from the standard input to the standard output. Error messages such as
loop: can't get info on device /dev/loop1: No such device or address
go to the standard error. You can work around this by redirecting the standard error in the command which you pass to popen, e.g.,
sprintf(cmd, "losetup /dev/loop%d 2>&1", i);
because it is a shell command (and shells allow you to do redirection).

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

How this stdout redirection works?

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");

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.