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++?
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
dfprobably uses to get its information:statvfs().