From 780e0ab90da8c8eba423ba1bfc85c2a8e58ca1c6 Mon Sep 17 00:00:00 2001
From: Rakesh Pandit <rakesh@fedoraproject.org>
Date: Thu, 22 Oct 2009 15:13:42 +0530
Subject: [PATCH] Added new option --timeout-response to ping/ping6.

---
 ChangeLog          |   15 +++++++++++++++
 NEWS               |    4 +++-
 doc/inetutils.texi |    6 ++++++
 ping/ping.c        |   15 +++++++++++++++
 ping/ping6.c       |   15 +++++++++++++++
 ping/ping_common.c |   11 +++++++++++
 ping/ping_common.h |    1 +
 7 files changed, 66 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f89de16..bec5b14 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-10-22  Rakesh Pandit  <rakesh@fedoraproject.org>
+
+	* ping/ping_common.c (ping_set_timer): New function.
+	* ping/ping_common.h (ping_set_timer): New prototype.
+
+	* ping/ping6.c (argp_options): New option --timeout-response.
+	(parse_opt): New option --timeout-response and check for edge
+	values.
+	(ping_run): Set timer for response timeout via ping_set_timer and
+	corresponding signal for SIGALRM.
+	* ping/ping6.c: Likewise.
+
+	* doc/inetutils.texi (ping invocation): Updated.
+	* NEWS: Updated.
+
 2009-10-20  Rakesh Pandit  <rakesh@fedoraproject.org>
 
 	* ping/ping.c (parse_opt): Handle `--debug' and `--ignore-routing'
diff --git a/NEWS b/NEWS
index 30beda0..84a3dc8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU inetutils NEWS -- history of user-visible changes. 2009-10-06
+GNU inetutils NEWS -- history of user-visible changes. 2009-10-22
 
 Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 
 	  Free Software Foundation, Inc.
@@ -12,6 +12,8 @@ Version 1.7:
 
 * ping
 
+New option --timeout-response=N, wait N seconds for response.
+
 New option --timeout=N, stop sending packets after N seconds.
 
 * New logger implementation
diff --git a/doc/inetutils.texi b/doc/inetutils.texi
index aba0c28..235505c 100644
--- a/doc/inetutils.texi
+++ b/doc/inetutils.texi
@@ -474,6 +474,12 @@ the 8 bytes of ICMP header data.
 @opindex -w
 @opindex --timeout
 Stop after @var{n} seconds.
+
+@item -W @var{n}
+@itemx --timeout-response=@var{n}
+@opindex -W
+@opindex --timeout-response
+Wait @var{n} seconds for response.
 @end table
 
 @section Using ping for network fault isolation
diff --git a/ping/ping.c b/ping/ping.c
index b194c38..8a8ab8e 100644
--- a/ping/ping.c
+++ b/ping/ping.c
@@ -68,6 +68,7 @@ size_t data_length = PING_DATALEN;
 unsigned options;
 unsigned long preload = 0;
 int timeout = -1;
+unsigned long timeout_response = -1;
 int (*ping_type) (char *hostname) = ping_echo;
 
 int (*decode_type (const char *arg)) (char *hostname);
@@ -115,6 +116,7 @@ static struct argp_option argp_options[] = {
    "network", GRP+1},
   {"verbose", 'v', NULL, 0, "verbose output", GRP+1},
   {"timeout", 'w', "N", 0, "stop after N seconds", GRP+1},
+  {"timeout-response", 'W', "N", 0, "wait N seconds for response", GRP+1},
 #undef GRP
 #define GRP 20
   {NULL, 0, NULL, 0, "Options valid for --echo requests:", GRP},
@@ -182,6 +184,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
       timeout = ping_cvt_number (arg, INT_MAX, 0);
       break;
 
+    case 'W':
+      timeout_response = strtoul (arg, &endptr, 0);
+      if (*endptr || timeout_response < 0
+          || timeout_response > INT_MAX/1000000) {
+        error (EXIT_FAILURE, 0, "invalid response timeout value (%s)", arg);
+      }
+      timeout_response *= 1000000;
+      break;
+
     case 'R':
       options |= OPT_RROUTE;
       break;
@@ -324,6 +335,7 @@ ping_run (PING * ping, int (*finish) ())
   int i;
 
   signal (SIGINT, sig_int);
+  signal (SIGALRM, sig_int);
 
   fdmax = ping->ping_fd + 1;
 
@@ -365,6 +377,9 @@ ping_run (PING * ping, int (*finish) ())
       if (resp_time.tv_sec < 0)
 	resp_time.tv_sec = resp_time.tv_usec = 0;
 
+      if (timeout_response != -1)
+	ping_set_timer (timeout_response);
+
       n = select (fdmax, &fdset, NULL, NULL, &resp_time);
       if (n < 0)
 	{
diff --git a/ping/ping6.c b/ping/ping6.c
index a65b875..5924796 100644
--- a/ping/ping6.c
+++ b/ping/ping6.c
@@ -55,6 +55,7 @@ size_t count = DEFAULT_PING_COUNT;
 size_t interval;
 int socket_type;
 int timeout = -1;
+unsigned long timeout_response = -1;
 static unsigned int options;
 static unsigned long preload = 0;
 
@@ -82,6 +83,7 @@ static struct argp_option argp_options[] = {
   {"ignore-routing", 'r', NULL, 0, "send directly to a host on an attached "
    "network", GRP+1},
   {"timeout", 'w', "N", 0, "stop after N seconds", GRP+1},
+  {"timeout-response", 'W', "N", 0, "wait N seconds for response", GRP+1},
 #undef GRP
 #define GRP 10
   {NULL, 0, NULL, 0, "Options valid for --echo requests:", GRP},
@@ -157,6 +159,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
       timeout = ping_cvt_number (arg, INT_MAX, 0);
       break;
 
+    case 'W':
+      timeout_response = strtoul (arg, &endptr, 0);
+      if (*endptr || timeout_response < 0
+          || timeout_response > INT_MAX/1000000) {
+        error (EXIT_FAILURE, 0, "invalid response timeout value (%s)", arg);
+      }
+      timeout_response *= 1000000;
+      break;
+
     case 's':
       data_length = ping_cvt_number (arg, PING_MAX_DATALEN, 1);
       break;
@@ -280,6 +291,7 @@ ping_run (PING * ping, int (*finish) ())
   int i;
 
   signal (SIGINT, sig_int);
+  signal (SIGALRM, sig_int);
 
   fdmax = ping->ping_fd + 1;
 
@@ -321,6 +333,9 @@ ping_run (PING * ping, int (*finish) ())
       if (resp_time.tv_sec < 0)
 	resp_time.tv_sec = resp_time.tv_usec = 0;
 
+      if (timeout_response != -1)
+	ping_set_timer (timeout_response);
+
       n = select (fdmax, &fdset, NULL, NULL, &resp_time);
       if (n < 0)
 	{
diff --git a/ping/ping_common.c b/ping/ping_common.c
index 9abb002..bb3d723 100644
--- a/ping/ping_common.c
+++ b/ping/ping_common.c
@@ -229,3 +229,14 @@ ping_timeout_p (struct timeval *start_time, int timeout)
     }
   return 0;
 }
+
+void
+ping_set_timer (int timeout_response)
+{
+  struct itimerval it_timeout;
+  it_timeout.it_interval.tv_sec = 0;
+  it_timeout.it_interval.tv_usec = 0;
+  it_timeout.it_value.tv_sec = timeout_response / 1000000;
+  it_timeout.it_value.tv_usec = timeout_response % 1000000;
+  setitimer (ITIMER_REAL, &it_timeout, NULL);
+}
diff --git a/ping/ping_common.h b/ping/ping_common.h
index ac1b6a5..695e4ca 100644
--- a/ping/ping_common.h
+++ b/ping/ping_common.h
@@ -158,4 +158,5 @@ void ping_set_sockopt (PING * ping, int opt, void *val, int valsize);
 void ping_set_interval (PING * ping, size_t interval);
 void ping_unset_data (PING * p);
 int ping_timeout_p (struct timeval *start_time, int timeout);
+void ping_set_timer (int timeout_response);
 
-- 
1.6.2.5

