Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing output of ping in c

Tags:

c

linux

pipeline

How can I capture the output of ping command via pipeline immediately ?

Here is my code:

int main ()
{
    FILE *cmd = popen ( "ping -c 3 google.com | grep icmp", "r" );//ping google
    char *s = malloc ( sizeof ( char ) * 200 );
    while ( 1 )
    {
            fgets ( s, sizeof ( char )*200, cmd );
            printf ( "%s", s);//show outcome
            if ( strstr ( s, "icmp_req=3" ) != 0 )
                    break;
    }
    pclose ( cmd );
    return 0;
}

When the program finished, it will show the output at the same time. But I would like to read the output immediately while the program execute.

like image 216
CJD Avatar asked Jan 22 '13 06:01

CJD


2 Answers

<stdio.h> is buffered by default, and stdout is line-buffered.

Replace your printf("%s", s); with printf("%s\n", s); (the ending newline would flush the stdout buffer) or add a call to fflush(NULL); just after it.

Actually, your question is unrelated to ping, but the pipe is buffered.

You might do the lower level pipe, fork, dup2, read syscalls and manage explicitly the buffer on the pipe. Then calling poll could be useful.

You could consider using a ICMP pinging library like liboping or consider instead doing an HTTP request (either using the wget program, or preferably libcurl; perhaps a simple HTTP HEAD request could be enough). As a general advice avoid forking a process with popen or system (because the commands available might not be the same on the target computer).

Read some good Linux programming book, like http://advancedlinuxprogramming.com/

like image 111
Basile Starynkevitch Avatar answered Sep 21 '22 19:09

Basile Starynkevitch


Here is a small code that uses liboping to ping www.xively.com every second and display the latency. You can install liboping static/dynamic library files and header files on your ubuntu box like so: sudo apt-get install liboping0 liboping-dev oping

Then compile the following program with the above library (gcc -o test test.c -loping). And run the executable as a super user (sudo).

test.c:

 /*
  * 1. install liboping, e.g. `sudo apt-get install liboping0 liboping-dev oping`
  * 2. Compile with -loping, e.g. `gcc -o test test.c -loping`
  * 3. Execute using sudo as super user, e.g. `sudo ./test`
  */

#include <stdlib.h>
#include <stdio.h>
#include <oping.h>

int main(int argc, char **argv) {
    pingobj_t *ping;
    pingobj_iter_t *iter;

    if ((ping = ping_construct()) == NULL) {
        fprintf(stderr, "ping_construct failed\n");
        return -1;
    }
    printf("ping_construct() success\n");

    if (ping_host_add(ping, "www.xively.com") < 0) {
        const char * errmsg = ping_get_error(ping);
        fprintf(stderr, "ping_host_add(www.xively.com) failed. %s\n", errmsg);
        return -1;
    }
    printf("ping_host_add() success\n");

    while (1) {
        if (ping_send(ping) < 0) {
            fprintf(stderr, "ping_send failed\n");
            return -1;
        }
        printf("ping_send() success\n");

        for (iter = ping_iterator_get(ping); iter != NULL; iter =
                ping_iterator_next(iter)) {
            char hostname[100];
            double latency;
            unsigned int len;

            printf("ping_iterator_get() success\n");
            len = 100;
            ping_iterator_get_info(iter, PING_INFO_HOSTNAME, hostname, &len);
            len = sizeof(double);
            ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len);

            printf("hostname = %s, latency = %f\n", hostname, latency);
        }
        sleep(1);
    }
    printf("exiting...\n");

    ping_destroy( ping );

    return 0;
}

Output:

anurag@anurag-PC:~$ sudo ./test
ping_construct() success
ping_host_add() success
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 233.666000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.360000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.076000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 231.761000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 235.085000
^C

liboping is good if you want to check for internet connectivity from your linux device provided your ISP or target does not block ICMP packets. If these are blocked, you can use some HTTP library to try and fetch the index.html page from www.google.com or any other website and check if that succeeds

like image 33
lithiumhead Avatar answered Sep 20 '22 19:09

lithiumhead