I am trying to update squidclient support multiple protocol request messages (HTTP/1, HTTP/2, HTCP, ICP).

The attached patch begins breaking the existing code into modules. The "ping mode" operations and command line processing are broken out from the main squidclient.cc into Ping.* files.

To keep the tool code files clearly identifiable now that they are multiplying they are shuffled into tools/squidclient/

A mechanism is added to allow each module to have its own option set. Ping-specific short command line options are now only parsed after a mode flag (--ping) is presented. This frees up the -g and -I options for use by other non-ping modules in future.

Amos
=== modified file 'configure.ac'
--- configure.ac        2014-02-13 07:02:35 +0000
+++ configure.ac        2014-02-16 12:15:21 +0000
@@ -3483,6 +3483,7 @@
        helpers/storeid_rewrite/Makefile
        helpers/storeid_rewrite/file/Makefile
        tools/Makefile
+       tools/squidclient/Makefile
        tools/purge/Makefile
 ])
 

=== modified file 'src/cbdata.cc'
--- src/cbdata.cc       2014-02-11 12:02:07 +0000
+++ src/cbdata.cc       2014-02-16 21:03:42 +0000
@@ -48,9 +48,9 @@
 
 #include "squid.h"
 #include "cbdata.h"
+#include "Generic.h"
 #include "mgr/Registration.h"
 #include "Store.h"
-#include "Generic.h"
 
 #if HAVE_LIMITS_H
 #include <limits.h>

=== modified file 'tools/Makefile.am'
--- tools/Makefile.am   2013-06-01 13:05:38 +0000
+++ tools/Makefile.am   2014-02-16 21:04:32 +0000
@@ -11,7 +11,7 @@
 ## we need our local files too (but avoid -I. at all costs)
 INCLUDES += -I$(srcdir)
 
-SUBDIRS = purge
+SUBDIRS = squidclient purge
 EXTRA_DIST = 
 man_MANS = 
 DISTCLEANFILES = 
@@ -52,19 +52,6 @@
 ## Test Scripts
 EXTRA_DIST += helper-ok-dying.pl helper-ok.pl
 
-## ##### squidclient  #####
-
-bin_PROGRAMS = squidclient
-
-squidclient_SOURCES = squidclient.cc \
-       stub_debug.cc \
-       test_tools.cc \
-       time.cc
-
-EXTRA_DIST += squidclient.1
-man_MANS += squidclient.1
-
-
 
 ## ##### cachemgr.cgi  #####
 

=== added directory 'tools/squidclient'
=== added file 'tools/squidclient/Parameters.h'
--- tools/squidclient/Parameters.h      1970-01-01 00:00:00 +0000
+++ tools/squidclient/Parameters.h      2014-02-16 21:10:45 +0000
@@ -0,0 +1,25 @@
+#ifndef _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H
+#define _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H
+
+/**
+ * squidclient command line parameters.
+ */
+class Parameters
+{
+public:
+    Parameters() : verbosityLevel(0) {}
+
+    /**
+     * What verbosity level to display.
+     *
+     *  0  : display no debug traces
+     *  1  : display outgoing request message
+     *  2+ : display all actions taken
+     */
+    int verbosityLevel;
+};
+
+/// global squidcleint parameters
+extern Parameters scParams;
+
+#endif /* _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H */

=== added file 'tools/squidclient/Ping.cc'
--- tools/squidclient/Ping.cc   1970-01-01 00:00:00 +0000
+++ tools/squidclient/Ping.cc   2014-02-16 21:13:54 +0000
@@ -0,0 +1,205 @@
+#include "squid.h"
+#include "SquidTime.h"
+#include "tools/squidclient/Parameters.h"
+#include "tools/squidclient/Ping.h"
+
+#include <iostream>
+
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+namespace Ping
+{
+Ping::TheConfig Config;
+
+/// measurements collected by the squidclient ping mode logics
+class pingStats_
+{
+public:
+    pingStats_() {memset(this, 0, sizeof(pingStats_));}
+
+    long counted;  ///< number of transactions which have so far been measured
+    long pMin;     ///< shortest transaction time seen
+    long pMax;     ///< longest transaction time seen
+    long sum;      ///< total time so far spent waiting on transactions
+
+} stats;
+
+} // namespace Ping
+
+/**
+ * Signal interrupt handler for squidclient ping.
+ * Displays final statistics and disables further pings.
+ */
+static void
+catchSignal(int sig)
+{
+    Ping::DisplayStats();
+    Ping::Config.enable = false;
+    std::cerr << "SIGNAL " << sig << " Interrupted." << std::endl;
+}
+
+uint32_t
+Ping::Init()
+{
+    if (Ping::Config.enable) {
+#if HAVE_SIGACTION
+        struct sigaction sa, osa;
+        if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
+            sa.sa_handler = catchSignal;
+            sa.sa_flags = 0;
+            sigemptyset(&sa.sa_mask);
+            (void) sigaction(SIGINT, &sa, NULL);
+        }
+#else
+        void (*osig) (int);
+        if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL)
+            (void) signal(SIGINT, osig);
+#endif
+        return Ping::Config.count;
+    }
+
+    return 1;
+}
+
+static struct timeval tv1, tv2;
+
+void
+Ping::TimerStart()
+{
+    if (!Ping::Config.enable)
+        return;
+
+#if GETTIMEOFDAY_NO_TZP
+    (void)gettimeofday(&tv1);
+#else
+    (void)gettimeofday(&tv1, NULL);
+#endif
+}
+
+void
+Ping::TimerStop(size_t fsize)
+{
+    if (!Ping::Config.enable)
+        return;
+
+    struct tm *tmp;
+    time_t t2s;
+    long elapsed_msec;
+
+#if GETTIMEOFDAY_NO_TZP
+    (void)gettimeofday(&tv2);
+#else
+    (void)gettimeofday(&tv2, NULL);
+#endif
+
+    elapsed_msec = tvSubMsec(tv1, tv2);
+    t2s = tv2.tv_sec;
+    tmp = localtime(&t2s);
+    char tbuf[4096];
+    snprintf(tbuf, sizeof(tbuf)-1, "%d-%02d-%02d %02d:%02d:%02d [%d]: 
%ld.%03ld secs, %f KB/s",
+             tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+             tmp->tm_hour, tmp->tm_min, tmp->tm_sec, stats.counted + 1,
+             elapsed_msec / 1000, elapsed_msec % 1000,
+             elapsed_msec ? (double) fsize / elapsed_msec : -1.0);
+    std::cerr << tbuf << std::endl;
+
+    if (!stats.counted || elapsed_msec < stats.pMin)
+        stats.pMin = elapsed_msec;
+
+    if (!stats.counted || elapsed_msec > stats.pMax)
+        stats.pMax = elapsed_msec;
+
+    stats.sum += elapsed_msec;
+
+    ++stats.counted;
+
+    /* Delay until next "ping.interval" boundary */
+    if (!LoopDone(stats.counted) && elapsed_msec < Ping::Config.interval) {
+
+        struct timeval tvs;
+        long msec_left = Ping::Config.interval - elapsed_msec;
+
+        tvs.tv_sec = msec_left / 1000;
+        tvs.tv_usec = (msec_left % 1000) * 1000;
+        select(0, NULL, NULL, NULL, &tvs);
+    }
+}
+
+void
+Ping::DisplayStats()
+{
+    if (Ping::Config.enable && stats.counted) {
+        long mean = stats.sum / stats.counted;
+        std::cerr << stats.counted << " requests, round-trip (secs) 
min/avg/max = "
+                  << (stats.pMin/1000) << "." << (stats.pMin%1000)
+                  << "/" << (mean/1000) << "." << (mean%1000)
+                  << "/" << (stats.pMax/1000) << "." << (stats.pMax%1000)
+                  << std::endl;
+    }
+}
+
+void
+Ping::TheConfig::usage()
+{
+    std::cerr << "Ping Mode" << std::endl
+              << "  --ping [options]  Enable ping mode." << std::endl
+              << std::endl
+              << "  options:" << std::endl
+              << "    -g count        Ping iteration count (default, loop 
until interrupted)." << std::endl
+              << "    -I interval     Ping interval in seconds (default 1 
second)." << std::endl
+              << std::endl;
+}
+
+bool
+Ping::TheConfig::parseCommandOpts(int argc, char *argv[], int c, int &optIndex)
+{
+    // to get here --ping was seen
+    enable = true;
+    count = 0;           // default is infinite loop
+    interval = 1 * 1000; // default is 1s intervals
+
+    const char *shortOpStr = "g:I:?";
+
+    // options for controlling squidclient ping mode
+    static struct option pingOptions[] = {
+        {"count",    no_argument, 0, 'g'},
+        {"interval", no_argument, 0, 'I'},
+        {0, 0, 0, 0}
+    };
+
+    int saved_opterr = opterr;
+    opterr = 0; // suppress errors from getopt
+    while ((c = getopt_long(argc, argv, shortOpStr, pingOptions, &optIndex)) 
!= -1) {
+        switch (c) {
+        case 'g':
+            if (optarg)
+                count = atoi(optarg);
+            else {
+                std::cerr << "ERROR: -g ping count missing parameter." << 
std::endl;
+                usage();
+            }
+            break;
+
+        case 'I':
+            if ((interval = atoi(optarg) * 1000) <= 0) {
+                std::cerr << "ERROR: -I ping interval out of range (0-" << 
(INT_MAX/1000) << ")." << std::endl;
+                usage();
+            }
+            break;
+
+        default:
+            // rewind and let the caller handle unknown options
+            --optind;
+            opterr = saved_opterr;
+            return true;
+        }
+    }
+
+    opterr = saved_opterr;
+    return false;
+}

=== added file 'tools/squidclient/Ping.h'
--- tools/squidclient/Ping.h    1970-01-01 00:00:00 +0000
+++ tools/squidclient/Ping.h    2014-02-16 21:04:33 +0000
@@ -0,0 +1,54 @@
+#ifndef _SQUID_TOOLS_CLIENT_PING_H
+#define _SQUID_TOOLS_CLIENT_PING_H
+
+/**
+ * API for looping the squidclient request message
+ * repeatedly.
+ */
+namespace Ping
+{
+
+/// parameters controlling 'ping' mode message looping.
+class TheConfig
+{
+public:
+    TheConfig() : enable(false), count(0), interval(1*1000) {}
+
+    /// display Ping Options command line help to stderr
+    void usage();
+
+    /**
+     * parse --ping command line options
+     * \return true if there are other options still to parse
+     */
+    bool parseCommandOpts(int argc, char *argv[], int c, int &optIndex);
+
+    bool enable;
+    int count;
+    int interval;
+};
+
+extern TheConfig Config;
+
+/// initialize the squidclient ping mode
+uint32_t Init();
+
+/// whether ping loop is completed at the given iteration.
+inline bool LoopDone(int i)
+{
+    return !Ping::Config.enable || (Ping::Config.count && i >= 
Ping::Config.count);
+}
+
+/// start timing a new transaction
+void TimerStart();
+
+/// calculate and display the statictics for a complete transaction
+/// \param fsize number of bytes transferred during this transaction (for KB/s 
measure)
+void TimerStop(size_t fsize);
+
+/// display summary of ping data collected
+void DisplayStats();
+
+} // namespace Ping
+
+#endif /* _SQUID_TOOLS_CLIENT_PING_H */

=== renamed file 'tools/squidclient.1' => 'tools/squidclient/squidclient.1'
--- tools/squidclient.1 2013-04-23 12:25:33 +0000
+++ tools/squidclient/squidclient.1     2014-02-16 21:48:35 +0000
@@ -7,18 +7,15 @@
 .
 .SH SYNOPSIS
 .if !'po4a'hide' .B squidclient
+.if !'po4a'hide' .B "[ \-\-ping [ping-options] ] "
 .if !'po4a'hide' .B "[ \-aknNrsv ] [ \-A"
 string
-.if !'po4a'hide' .B "] [ \-g"
-count
 .if !'po4a'hide' .B "] [ \-h"
 remote host
 .if !'po4a'hide' .B "] [ \-H '"
 string
 .if !'po4a'hide' .B "' ] [ \-i"
 IMS
-.if !'po4a'hide' .B "] [ \-I"
-ping interval
 .if !'po4a'hide' .B "] [ \-j '"
 Host header
 .if !'po4a'hide' .B "' ] [ \-l"
@@ -46,6 +43,12 @@
 .if !'po4a'hide' .B "] "
 url
 .
+.if !'po4a'hide' .B "Ping options: [ \-g"
+count
+.if !'po4a'hide' .B "] [ \-I"
+interval
+.if !'po4a'hide' .B "] "
+.
 .SH DESCRIPTION
 .B squidclient
 is a tool providing a command line interface for retrieving URLs.
@@ -67,12 +70,6 @@
 as User-Agent: header. To omit the header completely set string to empty ('').
 .
 .if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-g count"
-Ping mode, perform
-.I count
-iterations (0 to loop until interrupted).
-.
-.if !'po4a'hide' .TP
 .if !'po4a'hide' .B "\-h host"
 Retrieve URL from cache on hostname.  Default is
 .B localhost
@@ -88,10 +85,6 @@
 If\-Modified\-Since time (in Epoch seconds).
 .
 .if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-I interval"
-Ping interval in seconds (default 1 second).
-.
-.if !'po4a'hide' .TP
 .if !'po4a'hide' .B "\-j hosthdr"
 Host header content
 .
@@ -184,6 +177,21 @@
 .if !'po4a'hide' .B "\-W password"
 WWW authentication password
 .
+.if !'po4a'hide' .TP 10
+.if !'po4a'hide' .B "\-\-ping [options]"
+Enable ping mode. Optional \-g and \-I parameters must follow immediately if 
used.
+Repeated use resets to default ping settings.
+.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B "\-g count"
+Ping mode, perform
+.I count
+iterations (default is to loop until interrupted).
+.
+.if !'po4a'hide' .TP
+.if !'po4a'hide' .B "\-I interval"
+Ping interval in seconds (default 1 second).
+.
 .SH AUTHOR
 Derived from Harvest. Further developed by by numerous individuals from
 the internet community. Development is led by Duane Wessels of the

=== renamed file 'tools/squidclient.cc' => 'tools/squidclient/squidclient.cc'
--- tools/squidclient.cc        2014-02-16 09:50:29 +0000
+++ tools/squidclient/squidclient.cc    2014-02-16 21:17:08 +0000
@@ -35,7 +35,8 @@
 #include "ip/Address.h"
 #include "ip/tools.h"
 #include "rfc1123.h"
-#include "SquidTime.h"
+#include "tools/squidclient/Parameters.h"
+#include "tools/squidclient/Ping.h"
 
 #if _SQUID_WINDOWS_
 /** \cond AUTODOCS-IGNORE */
@@ -118,29 +119,17 @@
 #define HEADERLEN      65536
 #endif
 
-typedef void SIGHDLR(int sig);
-
 /// display debug messages at varying verbosity levels
 #define debugVerbose(LEVEL, MESSAGE) \
-    while ((LEVEL) <= verbosityLevel) {std::cerr << MESSAGE << std::endl; 
break;}
-
-/**
- * What verbosity level to display.
- *
- *  0  : display no debug traces
- *  1  : display outgoing request message
- *  2+ : display all actions taken
- */
-int verbosityLevel = 0;
+    while ((LEVEL) <= scParams.verbosityLevel) {std::cerr << MESSAGE << 
std::endl; break;}
 
 /* Local functions */
 static int client_comm_bind(int, const Ip::Address &);
 
-static int client_comm_connect(int, const Ip::Address &, struct timeval *);
+static int client_comm_connect(int, const Ip::Address &);
 static void usage(const char *progname);
 
-static int Now(struct timeval *);
-SIGHDLR catchSignal;
+typedef void SIGHDLR(int sig);
 SIGHDLR pipe_handler;
 static void set_our_signal(void);
 static ssize_t myread(int fd, void *buf, size_t len);
@@ -151,6 +140,8 @@
 static char *GSSAPI_token(const char *server);
 #endif
 
+Parameters scParams;
+
 static int put_fd;
 static char *put_file = NULL;
 
@@ -178,54 +169,52 @@
 usage(const char *progname)
 {
     std::cerr << "Version: " << VERSION << std::endl
-            << "Usage: " << progname << " [Basic Options] [HTTP Options]" << 
std::endl
-            << std::endl
-            << "Basic Options:" << std::endl
-            << "    -g count        Ping mode, perform \"count\" iterations (0 
to loop until interrupted)." << std::endl
-            << "    -h host         Send message to server on 'host'.  Default 
is localhost." << std::endl
-            << "    -I interval     Ping interval in seconds (default 1 
second)." << std::endl
-            << "    -l host         Specify a local IP address to bind to.  
Default is none." << std::endl
-            << "    -p port         Port number on server to contact. Default 
is " << CACHE_HTTP_PORT << "." << std::endl
-            << "    -s | --quiet    Silent.  Do not print response message to 
stdout." << std::endl
-            << "    -T timeout      Timeout value (seconds) for read/write 
operations" << std::endl
-            << "    -v | --verbose  Verbose debugging. Repeat (-vv) to 
increase output level." << std::endl
-            << "                    Levels:" << std::endl
-            << "                      1 - Print outgoing request message to 
stderr." << std::endl
-            << "                      2 - Print action trace to stderr." << 
std::endl
-            << "    --help          Display this help text." << std::endl
-            << std::endl
-            << "HTTP Options:" << std::endl
-            << "    -a           Do NOT include Accept: header." << std::endl
-            << "    -A           User-Agent: header. Use \"\" to omit." << 
std::endl
-            << "    -H 'string'  Extra headers to send. Use '\\n' for new 
lines." << std::endl
-            << "    -i IMS       If-Modified-Since time (in Epoch seconds)." 
<< std::endl
-            << "    -j hosthdr   Host header content" << std::endl
-            << "    -k           Keep the connection active. Default is to do 
only one request then close." << std::endl
-            << "    -m method    Request method, default is GET." << std::endl
+              << "Usage: " << progname << " [Basic Options] [HTTP Options]" << 
std::endl
+              << std::endl
+              << "Basic Options:" << std::endl
+              << "    -h host         Send message to server on 'host'.  
Default is localhost." << std::endl
+              << "    -l host         Specify a local IP address to bind to.  
Default is none." << std::endl
+              << "    -p port         Port number on server to contact. 
Default is " << CACHE_HTTP_PORT << "." << std::endl
+              << "    -s | --quiet    Silent.  Do not print response message 
to stdout." << std::endl
+              << "    -T timeout      Timeout value (seconds) for read/write 
operations" << std::endl
+              << "    -v | --verbose  Verbose debugging. Repeat (-vv) to 
increase output level." << std::endl
+              << "                    Levels:" << std::endl
+              << "                      1 - Print outgoing request message to 
stderr." << std::endl
+              << "                      2 - Print action trace to stderr." << 
std::endl
+              << "    --help          Display this help text." << std::endl
+              << std::endl;
+    Ping::Config.usage();
+    std::cerr
+        << "HTTP Options:" << std::endl
+        << "    -a           Do NOT include Accept: header." << std::endl
+        << "    -A           User-Agent: header. Use \"\" to omit." << 
std::endl
+        << "    -H 'string'  Extra headers to send. Use '\\n' for new lines." 
<< std::endl
+        << "    -i IMS       If-Modified-Since time (in Epoch seconds)." << 
std::endl
+        << "    -j hosthdr   Host header content" << std::endl
+        << "    -k           Keep the connection active. Default is to do only 
one request then close." << std::endl
+        << "    -m method    Request method, default is GET." << std::endl
 #if HAVE_GSSAPI
-            << "    -n           Proxy Negotiate(Kerberos) authentication" << 
std::endl
-            << "    -N           WWW Negotiate(Kerberos) authentication" << 
std::endl
+        << "    -n           Proxy Negotiate(Kerberos) authentication" << 
std::endl
+        << "    -N           WWW Negotiate(Kerberos) authentication" << 
std::endl
 #endif
-            << "    -P file      Send content from the named file as request 
payload" << std::endl
-            << "    -r           Force cache to reload URL" << std::endl
-            << "    -t count     Trace count cache-hops" << std::endl
-            << "    -u user      Proxy authentication username" << std::endl
-            << "    -U user      WWW authentication username" << std::endl
-            << "    -V version   HTTP Version. Use '-' for HTTP/0.9 omitted 
case" << std::endl
-            << "    -w password  Proxy authentication password" << std::endl
-            << "    -W password  WWW authentication password" << std::endl
-    ;
+        << "    -P file      Send content from the named file as request 
payload" << std::endl
+        << "    -r           Force cache to reload URL" << std::endl
+        << "    -t count     Trace count cache-hops" << std::endl
+        << "    -u user      Proxy authentication username" << std::endl
+        << "    -U user      WWW authentication username" << std::endl
+        << "    -V version   HTTP Version. Use '-' for HTTP/0.9 omitted case" 
<< std::endl
+        << "    -w password  Proxy authentication password" << std::endl
+        << "    -W password  WWW authentication password" << std::endl
+        ;
     exit(1);
 }
 
-static int interrupted = 0;
 int
 main(int argc, char *argv[])
 {
     int conn, len, bytesWritten;
     uint16_t port;
     bool to_stdout, reload;
-    int ping, pcount;
     int keep_alive = 0;
     int opt_noaccept = 0;
 #if HAVE_GSSAPI
@@ -240,10 +229,7 @@
     time_t ims = 0;
     int max_forwards = -1;
 
-    struct timeval tv1, tv2;
-    int i = 0, loops;
-    long ping_int;
-    long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0;
+    int i = 0;
     const char *proxy_user = NULL;
     const char *proxy_password = NULL;
     const char *www_user = NULL;
@@ -259,9 +245,6 @@
     port = CACHE_HTTP_PORT;
     to_stdout = true;
     reload = false;
-    ping = 0;
-    pcount = 0;
-    ping_int = 1 * 1000;
 
     Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before 
parsing.
     if (argc < 2 || argv[argc-1][0] == '-') {
@@ -271,21 +254,37 @@
         url[BUFSIZ - 1] = '\0';
 
         int optIndex = 0;
-        const char *shortOpStr = 
"aA:h:j:V:l:P:i:kmnN:p:rsvt:g:p:I:H:T:u:U:w:W:?";
+        const char *shortOpStr = "aA:h:j:V:l:P:i:kmnN:p:rsvt:p:H:T:u:U:w:W:?";
 
         // options for controlling squidclient
-        static struct option basicOptions[] =
-        {
-          /* These are the generic options for squidclient itself */
-          {"help",    no_argument, 0, '?'},
-          {"verbose", no_argument, 0, 'v'},
-          {"quiet",   no_argument, 0, 's'},
-          {0, 0, 0, 0}
+        static struct option basicOptions[] = {
+            /* These are the generic options for squidclient itself */
+            {"help",    no_argument, 0, '?'},
+            {"verbose", no_argument, 0, 'v'},
+            {"quiet",   no_argument, 0, 's'},
+            {"ping",    no_argument, 0, '\1'},
+            {0, 0, 0, 0}
         };
 
         int c;
         while ((c = getopt_long(argc, argv, shortOpStr, basicOptions, 
&optIndex)) != -1) {
-            switch (c) {
+
+            // modules parse their own specific options
+            switch (c) {
+            case '\1':
+                to_stdout = 0;
+                if (Ping::Config.parseCommandOpts(argc, argv, c, optIndex))
+                    continue;
+                break;
+
+            default: // fall through to next switch
+                break;
+            }
+
+            switch (c) {
+
+            case '\0': // dummy value for end-of-options
+                break;
 
             case 'a':
                 opt_noaccept = 1;
@@ -346,17 +345,6 @@
                 max_forwards = atoi(optarg);
                 break;
 
-            case 'g':
-                ping = 1;
-                pcount = atoi(optarg);
-                to_stdout = 0;
-                break;
-
-            case 'I':
-                if ((ping_int = atoi(optarg) * 1000) <= 0)
-                    usage(argv[0]);
-                break;
-
             case 'H':
                 if (strlen(optarg)) {
                     char *t;
@@ -406,8 +394,8 @@
 
             case 'v':
                 /* undocumented: may increase verb-level by giving more -v's */
-                ++verbosityLevel;
-                debugVerbose(2, "verbosity level set to " << verbosityLevel);
+                ++scParams.verbosityLevel;
+                debugVerbose(2, "verbosity level set to " << 
scParams.verbosityLevel);
                 break;
 
             case '?':          /* usage */
@@ -575,30 +563,10 @@
 
     debugVerbose(1, "Request:" << std::endl << msg << std::endl << ".");
 
-    if (ping) {
-#if HAVE_SIGACTION
-
-        struct sigaction sa, osa;
-
-        if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
-            sa.sa_handler = catchSignal;
-            sa.sa_flags = 0;
-            sigemptyset(&sa.sa_mask);
-            (void) sigaction(SIGINT, &sa, NULL);
-        }
-#else
-        void (*osig) (int);
-
-        if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL)
-            (void) signal(SIGINT, osig);
-
-#endif
-
-    }
-    loops = ping ? pcount : 1;
+    uint32_t loops = Ping::Init();
 
     for (i = 0; loops == 0 || i < loops; ++i) {
-        int fsize = 0;
+        size_t fsize = 0;
         struct addrinfo *AI = NULL;
 
         debugVerbose(2, "Resolving... " << hostname);
@@ -642,7 +610,7 @@
 
         debugVerbose(2, "Connecting... " << hostname << " (" << iaddr << ")");
 
-        if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) {
+        if (client_comm_connect(conn, iaddr) < 0) {
             char hostnameBuf[MAX_IPSTRLEN];
             iaddr.toUrl(hostnameBuf, MAX_IPSTRLEN);
             std::cerr << "ERROR: Cannot connect to " << hostnameBuf
@@ -702,56 +670,13 @@
 
         (void) close(conn);    /* done with socket */
 
-        if (interrupted)
+        if (Ping::LoopDone(i))
             break;
 
-        if (ping) {
-
-            struct tm *tmp;
-            time_t t2s;
-            long elapsed_msec;
-
-            (void) Now(&tv2);
-            elapsed_msec = tvSubMsec(tv1, tv2);
-            t2s = tv2.tv_sec;
-            tmp = localtime(&t2s);
-            char tbuf[4096];
-            snprintf(tbuf, sizeof(tbuf)-1, "%d-%02d-%02d %02d:%02d:%02d [%d]: 
%ld.%03ld secs, %f KB/s",
-                    tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-                    tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1,
-                    elapsed_msec / 1000, elapsed_msec % 1000,
-                    elapsed_msec ? (double) fsize / elapsed_msec : -1.0);
-            std::cerr << tbuf << std::endl;
-
-            if (i == 0 || elapsed_msec < ping_min)
-                ping_min = elapsed_msec;
-
-            if (i == 0 || elapsed_msec > ping_max)
-                ping_max = elapsed_msec;
-
-            ping_sum += elapsed_msec;
-
-            /* Delay until next "ping_int" boundary */
-            if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) {
-
-                struct timeval tvs;
-                long msec_left = ping_int - elapsed_msec;
-
-                tvs.tv_sec = msec_left / 1000;
-                tvs.tv_usec = (msec_left % 1000) * 1000;
-                select(0, NULL, NULL, NULL, &tvs);
-            }
-        }
-    }
-
-    if (ping && i) {
-        ping_mean = ping_sum / i;
-        std::cerr << i << " requests, round-trip (secs) min/avg/max = "
-                  << (ping_min/1000) << "." << (ping_min%1000)
-                  << "/" << (ping_mean/1000) << "." << (ping_mean%1000)
-                  << "/" << (ping_max/1000) << "." << (ping_max%1000)
-                  << std::endl;
-    }
+        Ping::TimerStop(fsize);
+    }
+
+    Ping::DisplayStats();
     return 0;
 }
 
@@ -768,34 +693,16 @@
 
 /// Set up the destination socket address for message to send to.
 static int
-client_comm_connect(int sock, const Ip::Address &addr, struct timeval *tvp)
+client_comm_connect(int sock, const Ip::Address &addr)
 {
     static struct addrinfo *AI = NULL;
     addr.getAddrInfo(AI);
     int res = connect(sock, AI->ai_addr, AI->ai_addrlen);
     Ip::Address::FreeAddrInfo(AI);
-    if (tvp)
-        (void) Now(tvp);
+    Ping::TimerStart();
     return res;
 }
 
-static int
-Now(struct timeval *tp)
-{
-#if GETTIMEOFDAY_NO_TZP
-    return gettimeofday(tp);
-#else
-    return gettimeofday(tp, NULL);
-#endif
-}
-
-void
-catchSignal(int sig)
-{
-    interrupted = 1;
-    std::cerr << "SIGNAL " << sig << " Interrupted." << std::endl;
-}
-
 void
 pipe_handler(int sig)
 {

Reply via email to