Description: allow non-zero exit status if some ping fails Forwarded: yes Author: Barak A. Pearlmutter , Florian Forster Applied-Upstream: https://github.com/octo/liboping/commit/9631429 Last-Update: 2011-09-06 diff a/src/mans/oping.pod b/src/mans/oping.pod --- a/src/mans/oping.pod +++ b/src/mans/oping.pod @@ -166,6 +166,18 @@ I (ECN), even if the deprecated I (ToS) aliases were used to specify the bits of outgoing packets. +=item B<-Z> I + +If any hosts have a drop rate higher than I, where I is a +number between zero and 100 inclusively, exit with a non-zero exit status. +Since it is not possible to have a higher drop rate than 100%, passing this +limit will effectively disable the feature (the default). Setting the option to +zero means that the exit status will only be zero if I replies for I +hosts have been received. + +The exit status will indicate the number of hosts with more than I +packets lost, up to a number of 255 failing hosts. + =back =head1 COLORS diff a/src/oping.c b/src/oping.c --- a/src/oping.c +++ b/src/oping.c @@ -121,6 +121,7 @@ static char *opt_filename = NULL; static int opt_count = -1; static int opt_send_ttl = 64; static uint8_t opt_send_qos = 0; +static double opt_exit_status_threshold = 1.0; static int host_num = 0; @@ -265,6 +266,8 @@ static void usage_exit (const char *name, int status) /* {{{ */ " -I srcaddr source address\n" " -D device outgoing interface name\n" " -f filename filename to read hosts from\n" + " -Z percent Exit with non-zero exit status if more than this percentage of\n" + " probes timed out. (default: never)\n" "\noping "PACKAGE_VERSION", http://verplant.org/liboping/\n" "by Florian octo Forster \n" @@ -467,7 +470,7 @@ static int read_options (int argc, char **argv) /* {{{ */ while (1) { - optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:"); + optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:"); if (optchar == -1) break; @@ -538,6 +541,24 @@ static int read_options (int argc, char **argv) /* {{{ */ set_opt_send_qos (optarg); break; + case 'Z': + { + char *endptr = NULL; + double tmp; + + errno = 0; + tmp = strtod (optarg, &endptr); + if ((errno != 0) || (endptr == NULL) || (*endptr != 0) || (tmp < 0.0) || (tmp > 100.0)) + { + fprintf (stderr, "Ignoring invalid -Z argument: %s\n", optarg); + fprintf (stderr, "The \"-Z\" option requires a numeric argument between 0 and 100.\n"); + } + else + opt_exit_status_threshold = tmp / 100.0; + + break; + } + case 'h': usage_exit (argv[0], 0); break; @@ -623,7 +644,7 @@ static int update_stats_from_context (ping_context_t *ctx) /* {{{ */ average = context_get_average (ctx); deviation = context_get_stddev (ctx); - + mvwprintw (ctx->window, /* y = */ 2, /* x = */ 2, "rtt min/avg/max/sdev = %.3f/%.3f/%.3f/%.3f ms", ctx->latency_min, @@ -951,9 +972,13 @@ static void update_host_hook (pingobj_iter_t *iter, /* {{{ */ #endif } /* }}} void update_host_hook */ +/* Prints statistics for each host, cleans up the contexts and returns the + * number of hosts which failed to return more than the fraction + * opt_exit_status_threshold of pings. */ static int post_loop_hook (pingobj_t *ping) /* {{{ */ { pingobj_iter_t *iter; + int failure_count = 0; #if USE_NCURSES endwin (); @@ -973,6 +998,13 @@ static int post_loop_hook (pingobj_t *ping) /* {{{ */ context_get_packet_loss (context), context->latency_total); + { + double pct_failed = 1.0 - (((double) context->req_rcvd) + / ((double) context->req_sent)); + if (pct_failed > opt_exit_status_threshold) + failure_count++; + } + if (context->req_rcvd != 0) { double average; @@ -992,7 +1024,7 @@ static int post_loop_hook (pingobj_t *ping) /* {{{ */ context_destroy (context); } - return (0); + return (failure_count); } /* }}} int post_loop_hook */ int main (int argc, char **argv) /* {{{ */ @@ -1281,11 +1313,19 @@ int main (int argc, char **argv) /* {{{ */ opt_count--; } /* while (opt_count != 0) */ - post_loop_hook (ping); + /* Returns the number of failed hosts according to -Z. */ + status = post_loop_hook (ping); ping_destroy (ping); - return (0); + if (status == 0) + exit (EXIT_SUCCESS); + else + { + if (status > 255) + status = 255; + exit (status); + } } /* }}} int main */ /* vim: set fdm=marker : */