Can't get output result from 'g++' call - c++

I'm doing a system call in c++:
system( "g++ file1.cpp -o test" );
And I'm trying to get the result in the command line into a std::string object. The reason I'm doing that is to analyze the output of g++ in the case where g++ fails because there is an error in the cpp.
Here's the method I've built for that:
std::string CmdLineCall( std::string cmd )
{
FILE* pipe = _popen( cmd.c_str(), "r");
if( pipe == NULL )
{
return "error";
}
char* buffer;
long bufferSize = cmd.size();
size_t code;
std::string result;
buffer = ( char* )malloc( sizeof( char ) * bufferSize );
if( buffer == NULL )
{
return "error";
}
code = fread( buffer, 1, sizeof( buffer ), pipe );
if( code != bufferSize )
{
return "error";
}
result = buffer;
return result;
}
I've debugged it and it goes all the way to the end but result = "".
I've tried with a simple system( "pause" ) command and it works, but it doesn't work.
Can it have something to do with the fact that the g++ call fails because my cpp file is flawed?
Thanks

Using system() is probably not the best choice for this. You might have better results with popen(), since that lets you read the standard output of your command -- but I suspect that won't be enough here either (as I assume the compiler may also print to stderr and popen() doesn't give you that).
Your best bet is to provide your own variant of popen that includes support for both stdout and stderr (and if you search for "popen source" I'm sure you'll have a good starting point).
Edit: on a re-read of your post, I see you are using popen()… so I'm a bit confused about where system() comes into play since you wouldn't use both of them. Regardless, I still feel the problem is that stderr is important and popen() isn't giving that to you, so you'll need to go get it yourself; you could do that by rewriting popen() or you could just redirect your own stderr to the input channel of a pipe before you call popen().

Related

ftell always returns -1

I'm trying to write a function that will kill instances by program name in string
unsigned int kill_all_program_instances(const char * program_name){
int res;
char buf[1024];
string first;
string second;
int lSize, pid , pos;
string command="pidof ";
FILE *fd;
memset(buf,'\0',sizeof(buf));
fd=popen((command+program_name).c_str(),"r");
unsigned int mypid = getpid();
if(fd != NULL){
fseek (fd , 0 , SEEK_END);
lSize = ftell(fd);
rewind (fd);
if (lSize <= 0)
{
printf("lsize is %d\n",lSize);
pclose(fd);
return 0;
}
.....
}
This is just the beginning of the function, but I always get -1 for lSize.
I ran
pidof chromium-browse
and got
26487 19353 16993 11504 10960 10880 10868 10829 10825 10805 8607 8263 8154 8089 7764 3965 3950
however when I run
kill_all_program_instances('chromium-browse')
I still get -1 for lSize.
Any idea whats wrong with my code?
Thanks
Aside from the comment/answer about detecting errors for popen (which doesn't seem correct), I do believe the actual problem is that you are trying to use fseek/ftell on a pipe, which is not a valid operation. A pipe is not a "file" in the conventional sense, it's a stream of data where each data item can only be read once.
Just read using fscanf() or something similar, until it gives you an EOF.
popen() communicates with the spawned process using pipes. pipes are not seekable.
You simply cannot use fseek/ftell on the FILE* returned by popen, they will always fail.

fopen() failing

I have a C++ program that syncs files with a remote server when windows xp starts. A function that needs to open a public key file fails at fopen(). When I start the program myself (from within explorer) everything works fine. But when I add a startup key to the registry the function fails.
I traced the code through a debugger and everything's fine until the call to CreateFileA(). CreateFileA returns FILE_NOT_FOUND.
I removed the call to fopen() and replaced it with a call to CreateFileA() directly. Then I changed SECURITY_ATTRIBUTES to NULL after which the call to CreateFileA() works.
The problem is that the 3rd party library I'm using for my encryption needs a FILE* object instead of just the data read from the file. How can I solve my problem?
Here's the code I'm currently using:
if( !GetModuleFileNameA(NULL, Path, MAX_PATH) ){
delete [] buf;
delete [] Path;
return strerror( errno );
}
rPath = Path;
delete [] Path;
ret = rPath.find_last_of( '\\' );
if( ret == string::npos ){
delete [] buf;
return strerror( errno );
}
ret++;
rPath.erase( rPath.begin() + ret, rPath.begin() + rPath.size() - ret );
rPath += "rsa_pub.txt";
if( ( f = fopen( rPath.c_str(), "rb" ) ) == NULL ){ // fails when started from registry
delete [] buf;
return strerror( errno );
}
EDIT:
I found a hackery solution to the problem: if I free the runtime library and then reload it the problem goes away. However this isn't a very elegant solution. Is it perhaps possible to reset the runtime withouth removing and reloading the dll?
Your rPath.erase call doesn't seem to make much sense
rPath.erase( rPath.begin() + ret, rPath.begin() + rPath.size() - ret );
What is that supposed to do?
Here you are using the (iterator, iterator) version of erase here. I beleve you are trying to erase the tail portion of the string beginning from the position ret. In that case I would expect it to look as
rPath.erase( rPath.begin() + ret, rPath.end() );
If you wanted to use the (position, length) version of erase, then it would look as
rPath.erase( ret, rPath.size() - ret );
But your specific usage looks like a weird hybrid of the two. What are you trying to do by that call?
The GetModuleFileNameA probably returns different strings, depending on how you start your program, which is why your code might appear to "work" in some cases.

C++ system() function — How to collect the output of the issued command?

I'm running some commands with the C++ system() function:
int system ( const char * command );
How can I collect the standard output from the issued commands?
To be specific, I want to collect the output of the issued command (for example, the directory listing output from issuing the dir command).
Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?
If the latter, use popen() and pclose() instead.
If the former, look at the return value from system() (and use the documentation for waitpid() to interpret it).
system() returns an int, so just grab it: int rvalue = system(command);
I believe the exact details of what system() will return are system-specific, though.
There are typically two ways for a system program to "return" a value: by writing to stdout, and by returning a status integer at the end of the program. (there are often more ways to return results, eg. by writing to a file or into a database, but I assume those are out of scope here).
For receiving the status code, just check the return value of the system function.
For receiving the output, either redirect it into a file, and read the file afterwards, or use popen.
The return value of system is (ironically) system-dependent, but in POSIX systems (including Linux, etc), it's the same as for wait -- low 8 or 16 bits are the exit status of the child (probably what you mean by "value returned by"), higher bits indicating what kind of signal terminated the child, if any. The URL to the manpage I've given supplies the preprocessor macros you can use to pry apart that return value!
There is no such thing as a "return string" of a program, as you've now clarified in a comment is what you desire; as another answer already mentioned, if you want the text which gets output by the other program, you should use popen instead of system.
Inspired by bmorin's attempt, but working and tested, this snippet will take a char* command and return a char* containing the results of executing that command...
// Calling function must free the returned result.
char* exec(const char* command) {
FILE* fp;
char* line = NULL;
// Following initialization is equivalent to char* result = ""; and just
// initializes result to an empty string, only it works with
// -Werror=write-strings and is so much less clear.
char* result = (char*) calloc(1, 1);
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&line, &len, fp) != -1) {
// +1 below to allow room for null terminator.
result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
// +1 below so we copy the final null terminator.
strncpy(result + strlen(result), line, strlen(line) + 1);
free(line);
line = NULL;
}
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
I looked into just editing bmorin's code, but would have had to change most lines, so a separate answer seemed more appropriate. Apologies if not. (Amongst other problems, bmorin's code didn't actually accumulate the lines; it printed them to stdout, where I presume they would not be wanted, since system() would have done that; and it returned void in one error path, when the function must return a char*, so the code wouldn't compile. Perhaps most egregious, it freed the result just before returning it.)
system() is declared and defined in libc. You can either read the first link I provided, or do man system at a command prompt in your shell.
I suggest the popen() functions, as said by other people as well,
but this problem is platform specific. the popen() function is
available on operating systems that use the POSIX API. I am not
sure if this command would work on other APIs like WIN32
Here is a code snippet (in plain C) executing a command with popen and returning its output:
char* exec(const char* command) {
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
}
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}

Why is fread reaching the EOF early?

I am writing a C library that reads a file into memory. It skips the first 54 bytes of the file (header) and then reads the remainder as data. I use fseek to determine the length of the file, and then use fread to read in the file.
The loop runs once and then ends because the EOF is reached (no errors). At the end, bytesRead = 10624, ftell(stream) = 28726, and the buffer contains 28726 values. I expect fread to read 30,000 bytes and the file position to be 30054 when EOF is reached.
C is not my native language so I suspect I've got a dumb beginner mistake somewhere.
Code is as follows:
const size_t headerLen = 54;
FILE * stream;
errno_t ferrno = fopen_s( &stream, filename.c_str(), "r" );
if(ferrno!=0) {
return -1;
}
fseek( stream, 0L, SEEK_END );
size_t bytesTotal = (size_t)(ftell( stream )) - headerLen; //number of data bytes to read
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-bytesRead,stream);
bytesRead+=result;
}
Depending on the reference you use, it's quite apparent that adding a "b" to the mode flag is the answer. Seeking nominations for the bonehead-badge. :-)
This reference talks about it in the second paragraph, second sentence (though not in their table).
MSDN doesn't discuss the binary flag until halfway down the page.
OpenGroup mentions the existance of the "b" tag, but states that it "shall have no effect".
perhaps it's a binary mode issue. Try opening the file with "r+b" as the mode.
EDIT: as noted in a comment "rb" is likely a better match to your original intent since "r+b" will open it for read/write and "rb" is read-only.
Also worth noting that simply including binmode.obj into your link command will do this for you for all file opens.
A solution, based on the previous answers:
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-
bytesRead,stream);
bytesRead+=result;
}

How do I read the results of a system() call in C++?

I'm using the following code to try to read the results of a df command in Linux using popen.
#include <iostream> // file and std I/O functions
int main(int argc, char** argv) {
FILE* fp;
char * buffer;
long bufSize;
size_t ret_code;
fp = popen("df", "r");
if(fp == NULL) { // head off errors reading the results
std::cerr << "Could not execute command: df" << std::endl;
exit(1);
}
// get the size of the results
fseek(fp, 0, SEEK_END);
bufSize = ftell(fp);
rewind(fp);
// allocate the memory to contain the results
buffer = (char*)malloc( sizeof(char) * bufSize );
if(buffer == NULL) {
std::cerr << "Memory error." << std::endl;
exit(2);
}
// read the results into the buffer
ret_code = fread(buffer, 1, sizeof(buffer), fp);
if(ret_code != bufSize) {
std::cerr << "Error reading output." << std::endl;
exit(3);
}
// print the results
std::cout << buffer << std::endl;
// clean up
pclose(fp);
free(buffer);
return (EXIT_SUCCESS);
}
This code is giving me a "Memory error" with an exit status of '2', so I can see where it's failing, I just don't understand why.
I put this together from example code that I found on Ubuntu Forums and C++ Reference, so I'm not married to it. If anyone can suggest a better way to read the results of a system() call, I'm open to new ideas.
EDIT to the original: Okay, bufSize is coming up negative, and now I understand why. You can't randomly access a pipe, as I naively tried to do.
I can't be the first person to try to do this. Can someone give (or point me to) an example of how to read the results of a system() call into a variable in C++?
You're making this all too hard. popen(3) returns a regular old FILE * for a standard pipe file, which is to say, newline terminated records. You can read it with very high efficiency by using fgets(3) like so in C:
#include <stdio.h>
char bfr[BUFSIZ] ;
FILE * fp;
// ...
if((fp=popen("/bin/df", "r")) ==NULL) {
// error processing and return
}
// ...
while(fgets(bfr,BUFSIZ,fp) != NULL){
// process a line
}
In C++ it's even easier --
#include <cstdio>
#include <iostream>
#include <string>
FILE * fp ;
if((fp= popen("/bin/df","r")) == NULL) {
// error processing and exit
}
ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor
string s;
while (! ins.eof()){
getline(ins,s);
// do something
}
There's some more error handling there, but that's the idea. The point is that you treat the FILE * from popen just like any FILE *, and read it line by line.
Why would std::malloc() fail?
The obvious reason is "because std::ftell() returned a negative signed number, which was then treated as a huge unsigned number".
According to the documentation, std::ftell() returns -1 on failure. One obvious reason it would fail is that you cannot seek in a pipe or FIFO.
There is no escape; you cannot know the length of the command output without reading it, and you can only read it once. You have to read it in chunks, either growing your buffer as needed or parsing on the fly.
But, of course, you can simply avoid the whole issue by directly using the system call df probably uses to get its information: statvfs().
(A note on terminology: "system call" in Unix and Linux generally refers to calling a kernel function from user-space code. Referring to it as "the results of a system() call" or "the results of a system(3) call" would be clearer, but it would probably be better to just say "capturing the output of a process.")
Anyway, you can read a process's output just like you can read any other file. Specifically:
You can start the process using pipe(), fork(), and exec(). This gives you a file descriptor, then you can use a loop to read() from the file descriptor into a buffer and close() the file descriptor once you're done. This is the lowest level option and gives you the most control.
You can start the process using popen(), as you're doing. This gives you a file stream. In a loop, you can read using from the stream into a temporary variable or buffer using fread(), fgets(), or fgetc(), as Zarawesome's answer demonstrates, then process that buffer or append it to a C++ string.
You can start the process using popen(), then use the nonstandard __gnu_cxx::stdio_filebuf to wrap that, then create an std::istream from the stdio_filebuf and treat it like any other C++ stream. This is the most C++-like approach. Here's part 1 and part 2 of an example of this approach.
I'm not sure you can fseek/ftell pipe streams like this.
Have you checked the value of bufSize ? One reason malloc be failing is for insanely sized buffers.
Thanks to everyone who took the time to answer. A co-worker pointed me to the ostringstream class. Here's some example code that does essentially what I was attempting to do in the original question.
#include <iostream> // cout
#include <sstream> // ostringstream
int main(int argc, char** argv) {
FILE* stream = popen( "df", "r" );
std::ostringstream output;
while( !feof( stream ) && !ferror( stream ))
{
char buf[128];
int bytesRead = fread( buf, 1, 128, stream );
output.write( buf, bytesRead );
}
std::string result = output.str();
std::cout << "<RESULT>" << std::endl << result << "</RESULT>" << std::endl;
return (0);
}
To answer the question in the update:
char buffer[1024];
char * line = NULL;
while ((line = fgets(buffer, sizeof buffer, fp)) != NULL) {
// parse one line of df's output here.
}
Would this be enough?
First thing to check is the value of bufSize - if that happens to be <= 0, chances are that malloc returns a NULL as you're trying to allocate a buffer of size 0 at that point.
Another workaround would be to ask malloc to provide you with a buffer of the size (bufSize + n) with n >= 1, which should work around this particular problem.
That aside, the code you posted is pure C, not C++, so including is overdoing it a little.
check your bufSize. ftell can return -1 on error, and this can lead to nonallocation by malloc with buffer having a NULL value.
The reason for the ftell to fail is, because of the popen. You cant search pipes.
Pipes are not random access. They're sequential, which means that once you read a byte, the pipe is not going to send it to you again. Which means, obviously, you can't rewind it.
If you just want to output the data back to the user, you can just do something like:
// your file opening code
while (!feof(fp))
{
char c = getc(fp);
std::cout << c;
}
This will pull bytes out of the df pipe, one by one, and pump them straight into the output.
Now if you want to access the df output as a whole, you can either pipe it into a file and read that file, or concatenate the output into a construct such as a C++ String.