Search code examples
c++popenoutputstream

C++ Read Continous Command Output stream like tcpdump


I would like to read the continuous output stream of commands like tcpdump from within a c++ program.

#include <iostream>
#include <string>
#include <stdio.h>


std::string outputcmd(std::string cmd){
    std::string data;
    char singlelinedata[1024];
    FILE * streamdata;
    streamdata = popen(cmd.c_str(), "r");
    cmd.append(" 2>&1");
    std::cout << feof(streamdata);
    if(streamdata){
        while(!feof(streamdata)){
            // if(fgets(singlelinedata, 1024, streamdata)  != NULL ){
            //     data.append(singlelinedata);
            // }
            if(fread(singlelinedata, 1024, sizeof(singlelinedata)/sizeof(singlelinedata),streamdata)){
                data.append(singlelinedata);
            }
        }
        pclose(streamdata);
    }
    return data;
}

int main(){

    std::string outp;
    outp = outputcmd("sudo tcpdump -i any -v");
    std::cout << outp;
    return 0;
}

It is giving me only the first line output of tcpdump -i any -v

enter image description here

I dont want to Write to file and read again like following. Make tcpdump -i any -v -w myfile to get it written on file and read continously


Solution

  • Try something like this:

    #include <iostream>
    #include <string>
    #include <stdio.h>
    
    
    void outputcmd(std::string cmd){
        char buffer[1024];
        FILE * pipef = popen(cmd.c_str(), "r");
        if(pipef){
            while(!feof(pipef)){
                int res;
                if((res = fread(buffer, /*note order here*/ 1, sizeof(buffer), pipef)) > 0){
                    std::string block(buffer, res);
                    std::cout << "read from pipe: [" << block << "] size " << block.size() << std::endl;
                }
            }
            pclose(pipef);
        }
    }
    
    int main(){
        outputcmd("sudo tcpdump -i any -v");
        return 0;
    }
    

    One note from the manpage

    Note that output popen() streams are block buffered by default.

    so you will get the results with some delay and in big chunks, not line by line.