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