1 Description: allow non-zero exit status if some ping fails
2 Forwarded: yes
3 Author: Barak A. Pearlmutter <barak+git@cs.nuim.ie>, Florian Forster <octo@verplant.org>
4 Applied-Upstream: https://github.com/octo/liboping/commit/9631429
5 Last-Update: 2011-09-06
7 diff a/src/mans/oping.pod b/src/mans/oping.pod
8 --- a/src/mans/oping.pod
9 +++ b/src/mans/oping.pod
10 @@ -166,6 +166,18 @@ I<Explicit Congestion Notification> (ECN), even if the deprecated
11 I<Type of Service> (ToS) aliases were used to specify the bits of outgoing
12 packets.
14 +=item B<-Z> I<percent>
15 +
16 +If any hosts have a drop rate higher than I<percent>, where I<percent> is a
17 +number between zero and 100 inclusively, exit with a non-zero exit status.
18 +Since it is not possible to have a higher drop rate than 100%, passing this
19 +limit will effectively disable the feature (the default). Setting the option to
20 +zero means that the exit status will only be zero if I<all> replies for I<all>
21 +hosts have been received.
22 +
23 +The exit status will indicate the number of hosts with more than I<percent>
24 +packets lost, up to a number of 255 failing hosts.
25 +
26 =back
28 =head1 COLORS
29 diff a/src/oping.c b/src/oping.c
30 --- a/src/oping.c
31 +++ b/src/oping.c
32 @@ -121,6 +121,7 @@ static char *opt_filename = NULL;
33 static int opt_count = -1;
34 static int opt_send_ttl = 64;
35 static uint8_t opt_send_qos = 0;
36 +static double opt_exit_status_threshold = 1.0;
38 static int host_num = 0;
40 @@ -265,6 +266,8 @@ static void usage_exit (const char *name, int status) /* {{{ */
41 " -I srcaddr source address\n"
42 " -D device outgoing interface name\n"
43 " -f filename filename to read hosts from\n"
44 + " -Z percent Exit with non-zero exit status if more than this percentage of\n"
45 + " probes timed out. (default: never)\n"
47 "\noping "PACKAGE_VERSION", http://verplant.org/liboping/\n"
48 "by Florian octo Forster <octo@verplant.org>\n"
49 @@ -467,7 +470,7 @@ static int read_options (int argc, char **argv) /* {{{ */
51 while (1)
52 {
53 - optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:");
54 + optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:");
56 if (optchar == -1)
57 break;
58 @@ -538,6 +541,24 @@ static int read_options (int argc, char **argv) /* {{{ */
59 set_opt_send_qos (optarg);
60 break;
62 + case 'Z':
63 + {
64 + char *endptr = NULL;
65 + double tmp;
66 +
67 + errno = 0;
68 + tmp = strtod (optarg, &endptr);
69 + if ((errno != 0) || (endptr == NULL) || (*endptr != 0) || (tmp < 0.0) || (tmp > 100.0))
70 + {
71 + fprintf (stderr, "Ignoring invalid -Z argument: %s\n", optarg);
72 + fprintf (stderr, "The \"-Z\" option requires a numeric argument between 0 and 100.\n");
73 + }
74 + else
75 + opt_exit_status_threshold = tmp / 100.0;
76 +
77 + break;
78 + }
79 +
80 case 'h':
81 usage_exit (argv[0], 0);
82 break;
83 @@ -623,7 +644,7 @@ static int update_stats_from_context (ping_context_t *ctx) /* {{{ */
85 average = context_get_average (ctx);
86 deviation = context_get_stddev (ctx);
87 -
88 +
89 mvwprintw (ctx->window, /* y = */ 2, /* x = */ 2,
90 "rtt min/avg/max/sdev = %.3f/%.3f/%.3f/%.3f ms",
91 ctx->latency_min,
92 @@ -951,9 +972,13 @@ static void update_host_hook (pingobj_iter_t *iter, /* {{{ */
93 #endif
94 } /* }}} void update_host_hook */
96 +/* Prints statistics for each host, cleans up the contexts and returns the
97 + * number of hosts which failed to return more than the fraction
98 + * opt_exit_status_threshold of pings. */
99 static int post_loop_hook (pingobj_t *ping) /* {{{ */
100 {
101 pingobj_iter_t *iter;
102 + int failure_count = 0;
104 #if USE_NCURSES
105 endwin ();
106 @@ -973,6 +998,13 @@ static int post_loop_hook (pingobj_t *ping) /* {{{ */
107 context_get_packet_loss (context),
108 context->latency_total);
110 + {
111 + double pct_failed = 1.0 - (((double) context->req_rcvd)
112 + / ((double) context->req_sent));
113 + if (pct_failed > opt_exit_status_threshold)
114 + failure_count++;
115 + }
116 +
117 if (context->req_rcvd != 0)
118 {
119 double average;
120 @@ -992,7 +1024,7 @@ static int post_loop_hook (pingobj_t *ping) /* {{{ */
121 context_destroy (context);
122 }
124 - return (0);
125 + return (failure_count);
126 } /* }}} int post_loop_hook */
128 int main (int argc, char **argv) /* {{{ */
129 @@ -1281,11 +1313,19 @@ int main (int argc, char **argv) /* {{{ */
130 opt_count--;
131 } /* while (opt_count != 0) */
133 - post_loop_hook (ping);
134 + /* Returns the number of failed hosts according to -Z. */
135 + status = post_loop_hook (ping);
137 ping_destroy (ping);
139 - return (0);
140 + if (status == 0)
141 + exit (EXIT_SUCCESS);
142 + else
143 + {
144 + if (status > 255)
145 + status = 255;
146 + exit (status);
147 + }
148 } /* }}} int main */
150 /* vim: set fdm=marker : */