Code

Implemented various options for the `oping' binary.
authorocto <octo>
Sat, 29 Apr 2006 11:13:32 +0000 (11:13 +0000)
committerocto <octo>
Sat, 29 Apr 2006 11:13:32 +0000 (11:13 +0000)
configure.ac
src/Makefile.am
src/oping.c

index 694188784cecd4f8e414c4e6c219092125bd6517..6f74c816f6bd2e6421481d11fe8b9d37127f9d1c 100644 (file)
@@ -32,6 +32,7 @@ AC_CONFIG_SUBDIRS(libltdl src)
 #
 AC_HEADER_STDC
 AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_HEADERS(math.h)
 AC_CHECK_HEADERS(fcntl.h)
 AC_CHECK_HEADERS(sys/types.h)
 AC_CHECK_HEADERS(sys/stat.h)
index 72f00cf8812a1f979faa75310c44fc2e9907186b..08e84455d86fb76ac70d3864864c7316379c99cf 100644 (file)
@@ -18,3 +18,7 @@ bin_PROGRAMS = oping
 
 oping_SOURCES = oping.c
 oping_LDADD = liboping.la
+oping_LDFLAGS = -lm
+if BUILD_WITH_LIBRT
+oping_LDFLAGS += -lrt
+endif
index e70988f34b1779ddfb77fd228e0298176b209d38..b18accf5c699e6768a1fc0c06669a06cc2d94bf3 100644 (file)
 # error "You don't have the standard C99 header files installed"
 #endif /* STDC_HEADERS */
 
+#if HAVE_MATH_H
+# include <math.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
 #if HAVE_NETDB_H
 # include <netdb.h> /* NI_MAXHOST */
 #endif
 
 #include <liboping.h>
 
+static double opt_interval   = 1.0;
+static int    opt_addrfamily = PING_DEF_AF;
+static int    opt_count      = -1;
+
+void usage_exit (const char *name)
+{
+       fprintf (stderr, "Usage: %s [-46] [-c count] [-i interval] host [host [host ...]]\n",
+                       name);
+       exit (1);
+}
+
+int read_options (int argc, char **argv)
+{
+       int optchar;
+
+       while (1)
+       {
+               optchar = getopt (argc, argv, "46c:i:");
+
+               if (optchar == -1)
+                       break;
+
+               switch (optchar)
+               {
+                       case '4':
+                       case '6':
+                               opt_addrfamily = (optchar == '4') ? AF_INET : AF_INET6;
+                               break;
+
+                       case 'c':
+                               {
+                                       int new_count;
+                                       new_count = atoi (optarg);
+                                       if (new_count > 0)
+                                               opt_count = new_count;
+                               }
+                               break;
+
+                       case 'i':
+                               {
+                                       double new_interval;
+                                       new_interval = atof (optarg);
+                                       if (new_interval >= 0.2)
+                                               opt_interval = new_interval;
+                               }
+                               break;
+
+                       default:
+                               usage_exit (argv[0]);
+               }
+       }
+
+       return (optind);
+}
+
+void print_host (pingobj_iter_t *iter)
+{
+       char     host[NI_MAXHOST];
+       char     addr[NI_MAXHOST];
+       double   latency;
+       uint16_t sequence;
+       size_t   buffer_len;
+
+       buffer_len = sizeof (host);
+       if (ping_iterator_get_info (iter, PING_INFO_HOSTNAME,
+                               host, &buffer_len) != 0)
+       {
+               fprintf (stderr, "ping_iterator_get_info failed.\n");
+               return;
+       }
+
+       buffer_len = sizeof (addr);
+       if (ping_iterator_get_info (iter, PING_INFO_ADDRESS,
+                               addr, &buffer_len) != 0)
+       {
+               fprintf (stderr, "ping_iterator_get_info failed.\n");
+               return;
+       }
+
+       buffer_len = sizeof (latency);
+       ping_iterator_get_info (iter, PING_INFO_LATENCY,
+                       &latency, &buffer_len);
+
+       buffer_len = sizeof (sequence);
+       ping_iterator_get_info (iter, PING_INFO_SEQUENCE,
+                       &sequence, &buffer_len);
+
+       printf ("echo reply from %s (%s): icmp_seq=%u time=%.1f ms\n",
+                       host, addr, (unsigned int) sequence, latency);
+}
+
+void time_normalize (struct timespec *ts)
+{
+       while (ts->tv_nsec < 0)
+       {
+               if (ts->tv_sec == 0)
+               {
+                       ts->tv_nsec = 0;
+                       return;
+               }
+
+               ts->tv_sec  -= 1;
+               ts->tv_nsec += 1000000000;
+       }
+
+       while (ts->tv_nsec >= 1000000000)
+       {
+               ts->tv_sec  += 1;
+               ts->tv_nsec -= 1000000000;
+       }
+}
+
+void time_calc (struct timespec *ts_dest,
+               const struct timespec *ts_int,
+               const struct timeval  *tv_begin,
+               const struct timeval  *tv_end)
+{
+       ts_dest->tv_sec = tv_begin->tv_sec + ts_int->tv_sec;
+       ts_dest->tv_nsec = (tv_begin->tv_usec * 1000) + ts_int->tv_nsec;
+       time_normalize (ts_dest);
+
+       /* Assure that `(begin + interval) > end'.
+        * This may seem overly complicated, but `tv_sec' is of type `time_t'
+        * which may be `unsigned. *sigh* */
+       if ((tv_end->tv_sec > ts_dest->tv_sec)
+                       || ((tv_end->tv_sec == ts_dest->tv_sec)
+                               && ((tv_end->tv_usec * 1000) > ts_dest->tv_nsec)))
+       {
+               ts_dest->tv_sec  = 0;
+               ts_dest->tv_nsec = 0;
+               return;
+       }
+
+       ts_dest->tv_sec = ts_dest->tv_sec - tv_end->tv_sec;
+       ts_dest->tv_nsec = ts_dest->tv_nsec - (tv_end->tv_usec * 1000);
+       time_normalize (ts_dest);
+}
+
 int main (int argc, char **argv)
 {
        pingobj_t      *ping;
        pingobj_iter_t *iter;
 
+       struct timeval  tv_begin;
+       struct timeval  tv_end;
+       struct timespec ts_wait;
+       struct timespec ts_int;
+
+       int optind;
        int i;
 
-       if (argc < 2)
-       {
-               printf ("Usage: %s <host> [host [host [...]]]\n", argv[0]);
-               return (1);
-       }
+
+       optind = read_options (argc, argv);
+
+       if (optind >= argc)
+               usage_exit (argv[0]);
 
        if ((ping = ping_construct ()) == NULL)
        {
@@ -56,7 +215,19 @@ int main (int argc, char **argv)
                return (1);
        }
 
-       for (i = 1; i < argc; i++)
+       {
+               double temp_sec;
+               double temp_nsec;
+
+               temp_sec = modf (opt_interval, &temp_nsec);
+               ts_int.tv_sec  = (time_t) temp_sec;
+               ts_int.tv_nsec = (long) (temp_nsec * 1000000000L);
+       }
+
+       if (opt_addrfamily != PING_DEF_AF)
+               ping_setopt (ping, PING_OPT_AF, (void *) &opt_addrfamily);
+
+       for (i = optind; i < argc; i++)
        {
                if (ping_host_add (ping, argv[i]) > 0)
                {
@@ -67,6 +238,17 @@ int main (int argc, char **argv)
 
        while (1)
        {
+               int status;
+
+               if (opt_count > 0)
+                       opt_count--;
+
+               if (gettimeofday (&tv_begin, NULL) < 0)
+               {
+                       perror ("gettimeofday");
+                       return (1);
+               }
+
                if (ping_send (ping) < 0)
                {
                        fprintf (stderr, "ping_send failed\n");
@@ -77,55 +259,32 @@ int main (int argc, char **argv)
                                iter != NULL;
                                iter = ping_iterator_next (iter))
                {
-                       char     host[NI_MAXHOST];
-                       char     addr[NI_MAXHOST];
-                       double   latency;
-                       uint16_t sequence;
-                       size_t   buffer_len;
-
-                       buffer_len = sizeof (host);
-                       if (ping_iterator_get_info (iter, PING_INFO_HOSTNAME,
-                                               host, &buffer_len) != 0)
-                       {
-                               fprintf (stderr, "ping_iterator_get_info failed.\n");
-                               continue;
-                       }
+                       print_host (iter);
+               }
+               fflush (stdout);
 
-                       buffer_len = sizeof (addr);
-                       if (ping_iterator_get_info (iter, PING_INFO_ADDRESS,
-                                               addr, &buffer_len) != 0)
-                       {
-                               fprintf (stderr, "ping_iterator_get_info failed.\n");
-                               continue;
-                       }
+               if (opt_count == 0)
+                       break;
 
-                       buffer_len = sizeof (latency);
-                       ping_iterator_get_info (iter, PING_INFO_LATENCY,
-                                       &latency, &buffer_len);
+               if (gettimeofday (&tv_end, NULL) < 0)
+               {
+                       perror ("gettimeofday");
+                       return (1);
+               }
 
-                       buffer_len = sizeof (sequence);
-                       ping_iterator_get_info (iter, PING_INFO_SEQUENCE,
-                                       &sequence, &buffer_len);
+               time_calc (&ts_wait, &ts_int, &tv_begin, &tv_end);
 
-                       printf ("echo reply from %s (%s): icmp_seq=%u time=%.1f ms\n",
-                                       host, addr, (unsigned int) sequence, latency);
+               while ((status = nanosleep (&ts_wait, &ts_wait)) != 0)
+               {
+                       if (errno != EINTR)
+                       {
+                               perror ("nanosleep");
+                               break;
+                       }
                }
+       } /* while (opt_count != 0) */
 
-               sleep (1);
-       }
+       ping_destroy (ping);
 
        return (0);
 }
-
-/*
- * octo@leeloo:~ $ ping verplant.org
- * PING verplant.org (213.95.21.52) 56(84) bytes of data.
- * 64 bytes from verplant.org (213.95.21.52): icmp_seq=1 ttl=57 time=141 ms
- * 64 bytes from verplant.org (213.95.21.52): icmp_seq=2 ttl=57 time=47.0 ms
- * 64 bytes from verplant.org (213.95.21.52): icmp_seq=3 ttl=57 time=112 ms
- * 64 bytes from verplant.org (213.95.21.52): icmp_seq=4 ttl=57 time=46.7 ms
- *
- * --- verplant.org ping statistics ---
- *  4 packets transmitted, 4 received, 0% packet loss, time 3002ms
- *  rtt min/avg/max/mdev = 46.782/86.870/141.373/41.257 ms
- */