From: Florian Forster Date: Thu, 25 Sep 2014 00:10:54 +0000 (-0700) Subject: Merge branch 'bp/exit' X-Git-Tag: liboping-1.7.0~4 X-Git-Url: https://git.octo.it/?p=liboping.git;a=commitdiff_plain;h=8557f59b71eb64324dcbb0e470bad9ca5958b2f0;hp=441f2f6f137275321d6bb3d8bfb35f414c580ab6 Merge branch 'bp/exit' Conflicts: src/mans/oping.pod src/oping.c --- diff --git a/.gitignore b/.gitignore index 8588514..e39f4fb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ src/noping *.o *.tar.gz *.tar.bz2 +bindings/perl/MYMETA.yml diff --git a/ChangeLog b/ChangeLog index 79f8483..600395f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,11 @@ -2011-03-13, Version 1.6.2: +2012-01-31, Version 1.6.2: * Build system: Setting capabilities and the set-UID bit has been made more fault-tolerant, so that it will work with Debian's fakeroot(1) utility. * src/liboping.c: Fixed a compiler warning about an non-static format string. Thanks to Brian Edwards for pointing this out. + * src/liboping.c: Fixed compilation under Mac OS X and Solaris. Thanks + to Clayton O'Neill for his patch. 2011-03-06, Version 1.6.1: * Build system: If "make install" is executed as root, the CAP_NET_RAW diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..f273d64 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +libtoolize +aclocal -I m4 +autoheader +automake --add-missing +autoconf +echo "autoconfiguration done, to build: ./configure ; make" diff --git a/configure.ac b/configure.ac index 40e3c55..f9be869 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_SUBST(LIBOPING_PATCH) # ABI version LIBOPING_CURRENT=2 -LIBOPING_REVISION=8 +LIBOPING_REVISION=9 LIBOPING_AGE=2 AC_SUBST(LIBOPING_CURRENT) AC_SUBST(LIBOPING_REVISION) @@ -48,7 +48,7 @@ LT_INIT([dlopen]) # Checks for header files. AC_HEADER_STDC AC_HEADER_TIME -AC_CHECK_HEADERS([math.h signal.h fcntl.h inttypes.h netdb.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) +AC_CHECK_HEADERS([math.h signal.h fcntl.h inttypes.h netdb.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h locale.h langinfo.h]) # This sucks, but what can I do..? AC_CHECK_HEADERS(netinet/in_systm.h, [], [], @@ -185,11 +185,25 @@ AC_CHECK_FUNCS(nanosleep, [], AC_MSG_ERROR(cannot find nanosleep))) AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes") -with_ncurses="yes" -AC_CHECK_HEADERS(ncurses.h, [with_ncurses="yes"], [with_ncurses="no"]) +with_ncurses="no" +AC_CHECK_HEADERS(ncursesw/ncurses.h ncurses.h, [with_ncurses="yes"], []) if test "x$with_ncurses" = "xyes" then - AC_CHECK_LIB(ncurses, mvwprintw, [with_ncurses="yes"], [with_ncurses="no"]) + have_ncursesw="no" + have_ncurses="no" + NCURSES_LIB="" + + AC_CHECK_LIB(ncursesw, mvwprintw, [have_ncursesw="yes"], [have_ncursesw="no"]) + AC_CHECK_LIB(ncurses, mvwprintw, [have_ncurses="yes"], [have_ncurses="no"]) + + if test "x$have_ncursesw" = "xyes"; then + NCURSES_LIB="-lncursesw" + else if test "x$have_ncurses" = "xyes"; then + NCURSES_LIB="-lncurses" + else + with_ncurses="no" + fi; fi + AC_SUBST(NCURSES_LIB) fi AM_CONDITIONAL(BUILD_WITH_LIBNCURSES, test "x$with_ncurses" = "xyes") diff --git a/src/Makefile.am b/src/Makefile.am index 1326783..844e0a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,7 +46,7 @@ bin_PROGRAMS += noping noping_SOURCES = oping.c noping_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_NCURSES=1 -noping_LDADD = liboping.la -lm -lncurses +noping_LDADD = liboping.la -lm $(NCURSES_LIB) if BUILD_WITH_LIBRT noping_LDADD += -lrt endif diff --git a/src/liboping.c b/src/liboping.c index 76a7d53..40a0ba2 100644 --- a/src/liboping.c +++ b/src/liboping.c @@ -17,6 +17,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef __APPLE__ +#define __APPLE_USE_RFC_3542 +#endif + #if HAVE_CONFIG_H # include #endif @@ -545,6 +549,7 @@ static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, sizeof (recv_qos)); dprintf ("TOSv6 = 0x%02"PRIx8";\n", recv_qos); } else +#ifdef IPV6_HOPLIMIT if (cmsg->cmsg_type == IPV6_HOPLIMIT) { memcpy (&recv_ttl, CMSG_DATA (cmsg), @@ -552,6 +557,25 @@ static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, dprintf ("TTLv6 = %i;\n", recv_ttl); } else +#endif +#ifdef IPV6_UNICAST_HOPS + if (cmsg->cmsg_type == IPV6_UNICAST_HOPS) + { + memcpy (&recv_ttl, CMSG_DATA (cmsg), + sizeof (recv_ttl)); + dprintf ("TTLv6 = %i;\n", recv_ttl); + } + else +#endif +#ifdef IPV6_MULTICAST_HOPS + if (cmsg->cmsg_type == IPV6_MULTICAST_HOPS) + { + memcpy (&recv_ttl, CMSG_DATA (cmsg), + sizeof (recv_ttl)); + dprintf ("TTLv6 = %i;\n", recv_ttl); + } + else +#endif { dprintf ("Not handling option %i.\n", cmsg->cmsg_type); @@ -613,6 +637,9 @@ static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph, return (0); } +/* Blocks until a packet was received from all hosts or the timeout is reached. + * When interrupted, (-EINTR) is returned. On error, -1 is returned. On + * success, returns zero. */ static int ping_receive_all (pingobj_t *obj) { fd_set read_fds; @@ -702,7 +729,8 @@ static int ping_receive_all (pingobj_t *obj) if ((status == -1) && (errno == EINTR)) { dprintf ("select was interrupted by signal..\n"); - continue; + ping_set_errno (obj, EINTR); + return (-EINTR); } else if (status < 0) { @@ -740,7 +768,7 @@ static int ping_receive_all (pingobj_t *obj) } /* while (1) */ return (ret); -} +} /* int ping_receive_all */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Sending functions: * @@ -1304,18 +1332,13 @@ int ping_setopt (pingobj_t *obj, int option, void *value) int ping_send (pingobj_t *obj) { - int ret; - if (obj == NULL) return (-1); if (ping_send_all (obj) < 0) return (-1); - if ((ret = ping_receive_all (obj)) < 0) - return (-2); - - return (ret); + return (ping_receive_all (obj)); } static pinghost_t *ping_host_search (pinghost_t *ph, const char *host) diff --git a/src/mans/oping.pod b/src/mans/oping.pod index 8b8c644..b6ce0b2 100644 --- a/src/mans/oping.pod +++ b/src/mans/oping.pod @@ -166,6 +166,11 @@ I (ECN), even if the deprecated I (ToS) aliases were used to specify the bits of outgoing packets. +=item B<-u>|B<-U> + +I B<-u> forces UTF-8 output, B<-U> disables UTF-8 output. If +neither is given, the codeset is automatically determined from the locale. + =item B<-Z> I If any hosts have a drop rate higher than I, where I is a diff --git a/src/oping.c b/src/oping.c index 762a3ea..6a82c59 100644 --- a/src/oping.c +++ b/src/oping.c @@ -74,13 +74,52 @@ #include #endif +#include +#include + #if USE_NCURSES # define NCURSES_OPAQUE 1 -# include +/* http://newsgroups.derkeiler.com/Archive/Rec/rec.games.roguelike.development/2010-09/msg00050.html */ +# define _X_OPEN_SOURCE_EXTENDED + +# if HAVE_NCURSESW_NCURSES_H +# include +# elif HAVE_NCURSES_H +# include +# endif # define OPING_GREEN 1 # define OPING_YELLOW 2 # define OPING_RED 3 +# define OPING_GREEN_HIST 4 +# define OPING_YELLOW_HIST 5 +# define OPING_RED_HIST 6 + +static char const * const hist_symbols_utf8[] = { + "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" }; +static size_t const hist_symbols_utf8_num = sizeof (hist_symbols_utf8) + / sizeof (hist_symbols_utf8[0]); + +/* scancodes for 6 levels of horizontal bars, ncurses-specific */ +/* those are not the usual constants because those are not constant */ +static int const hist_symbols_acs[] = { + 115, /* ACS_S9 "⎽" */ + 114, /* ACS_S7 "⎼" */ + 113, /* ACS_S5 "─" */ + 112, /* ACS_S3 "⎻" */ + 111 /* ACS_S1 "⎺" */ +}; +static size_t const hist_symbols_acs_num = sizeof (hist_symbols_acs) + / sizeof (hist_symbols_acs[0]); + +/* use different colors without a background for scancodes */ +static int const hist_colors_utf8[] = { + OPING_GREEN_HIST, OPING_YELLOW_HIST, OPING_RED_HIST }; +static int const hist_colors_acs[] = { + OPING_GREEN, OPING_YELLOW, OPING_RED }; +/* assuming that both arrays are the same size */ +static size_t const hist_colors_num = sizeof (hist_colors_utf8) + / sizeof (hist_colors_utf8[0]); #endif #include "oping.h" @@ -89,6 +128,10 @@ # define _POSIX_SAVED_IDS 0 #endif +#ifndef IPTOS_MINCOST +# define IPTOS_MINCOST 0x02 +#endif + /* Remove GNU specific __attribute__ settings when using another compiler */ #if !__GNUC__ # define __attribute__(x) /**/ @@ -122,6 +165,9 @@ 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; +#if USE_NCURSES +static int opt_utf8 = 0; +#endif static int host_num = 0; @@ -266,6 +312,9 @@ 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" +#if USE_NCURSES + " -u / -U force / disable UTF-8 output\n" +#endif " -Z percent Exit with non-zero exit status if more than this percentage of\n" " probes timed out. (default: never)\n" @@ -470,7 +519,11 @@ static int read_options (int argc, char **argv) /* {{{ */ while (1) { - optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:"); + optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:" +#if USE_NCURSES + "uU" +#endif + ); if (optchar == -1) break; @@ -541,6 +594,15 @@ static int read_options (int argc, char **argv) /* {{{ */ set_opt_send_qos (optarg); break; +#if USE_NCURSES + case 'u': + opt_utf8 = 2; + break; + case 'U': + opt_utf8 = 1; + break; +#endif + case 'Z': { char *endptr = NULL; @@ -618,12 +680,120 @@ static void time_calc (struct timespec *ts_dest, /* {{{ */ } /* }}} void time_calc */ #if USE_NCURSES -static int update_stats_from_context (ping_context_t *ctx) /* {{{ */ +static _Bool has_utf8() /* {{{ */ +{ +# if HAVE_NCURSESW_NCURSES_H + if (!opt_utf8) + { + /* Automatically determine */ + if (strcasecmp ("UTF-8", nl_langinfo (CODESET)) == 0) + opt_utf8 = 2; + else + opt_utf8 = 1; + } + return ((_Bool) (opt_utf8 - 1)); +# else + return (0); +# endif +} /* }}} _Bool has_utf8 */ + +static int update_prettyping_graph (ping_context_t *ctx, /* {{{ */ + double latency, unsigned int sequence) +{ + int color = OPING_RED; + char const *symbol = "!"; + int symbolc = '!'; + + int x_max; + int x_pos; + + x_max = getmaxx (ctx->window); + x_pos = ((sequence - 1) % (x_max - 4)) + 2; + + if (latency >= 0.0) + { + double ratio; + + size_t symbols_num = hist_symbols_acs_num; + size_t colors_num = 1; + + size_t index_symbols; + size_t index_colors; + size_t intensity; + + /* latency is in milliseconds, opt_interval is in seconds. */ + ratio = (latency * 0.001) / opt_interval; + if (ratio > 1) { + ratio = 1.0; + } + + if (has_utf8 ()) + symbols_num = hist_symbols_utf8_num; + + if (has_colors () == TRUE) + colors_num = hist_colors_num; + + intensity = (size_t) (ratio * ((double) (symbols_num * colors_num))); + if (intensity >= (symbols_num * colors_num)) + intensity = (symbols_num * colors_num) - 1; + + index_symbols = intensity % symbols_num; + assert (index_symbols < symbols_num); + + index_colors = intensity / symbols_num; + assert (index_colors < colors_num); + + if (has_utf8()) + { + color = hist_colors_utf8[index_colors]; + symbol = hist_symbols_utf8[index_symbols]; + } + else + { + color = hist_colors_acs[index_colors]; + symbolc = hist_symbols_acs[index_symbols] | A_ALTCHARSET; + } + } + else /* if (!(latency >= 0.0)) */ + wattron (ctx->window, A_BOLD); + + if (has_colors () == TRUE) + wattron (ctx->window, COLOR_PAIR(color)); + + if (has_utf8()) + mvwprintw (ctx->window, /* y = */ 3, /* x = */ x_pos, symbol); + else + mvwaddch (ctx->window, /* y = */ 3, /* x = */ x_pos, symbolc); + + if (has_colors () == TRUE) + wattroff (ctx->window, COLOR_PAIR(color)); + + /* Use negation here to handle NaN correctly. */ + if (!(latency >= 0.0)) + wattroff (ctx->window, A_BOLD); + + wprintw (ctx->window, " "); + return (0); +} /* }}} int update_prettyping_graph */ + +static int update_stats_from_context (ping_context_t *ctx, pingobj_iter_t *iter) /* {{{ */ { + double latency = -1.0; + size_t buffer_len = sizeof (latency); + + ping_iterator_get_info (iter, PING_INFO_LATENCY, + &latency, &buffer_len); + + unsigned int sequence = 0; + buffer_len = sizeof (sequence); + ping_iterator_get_info (iter, PING_INFO_SEQUENCE, + &sequence, &buffer_len); + + if ((ctx == NULL) || (ctx->window == NULL)) return (EINVAL); - werase (ctx->window); + /* werase (ctx->window); */ box (ctx->window, 0, 0); wattron (ctx->window, A_BOLD); @@ -653,6 +823,8 @@ static int update_stats_from_context (ping_context_t *ctx) /* {{{ */ deviation); } + update_prettyping_graph (ctx, latency, sequence); + wrefresh (ctx->window); return (0); @@ -669,7 +841,7 @@ static int on_resize (pingobj_t *ping) /* {{{ */ if ((height < 1) || (width < 1)) return (EINVAL); - main_win_height = height - (4 * host_num); + main_win_height = height - (5 * host_num); wresize (main_win, main_win_height, /* width = */ width); /* Allow scrolling */ scrollok (main_win, TRUE); @@ -693,9 +865,9 @@ static int on_resize (pingobj_t *ping) /* {{{ */ delwin (context->window); context->window = NULL; } - context->window = newwin (/* height = */ 4, + context->window = newwin (/* height = */ 5, /* width = */ width, - /* y = */ main_win_height + (4 * context->index), + /* y = */ main_win_height + (5 * context->index), /* x = */ 0); } @@ -743,9 +915,12 @@ static int pre_loop_hook (pingobj_t *ping) /* {{{ */ init_pair (OPING_GREEN, COLOR_GREEN, /* default = */ 0); init_pair (OPING_YELLOW, COLOR_YELLOW, /* default = */ 0); init_pair (OPING_RED, COLOR_RED, /* default = */ 0); + init_pair (OPING_GREEN_HIST, COLOR_GREEN, COLOR_BLACK); + init_pair (OPING_YELLOW_HIST, COLOR_YELLOW, COLOR_GREEN); + init_pair (OPING_RED_HIST, COLOR_RED, COLOR_YELLOW); } - main_win_height = height - (4 * host_num); + main_win_height = height - (5 * host_num); main_win = newwin (/* height = */ main_win_height, /* width = */ width, /* y = */ 0, /* x = */ 0); @@ -772,9 +947,9 @@ static int pre_loop_hook (pingobj_t *ping) /* {{{ */ delwin (context->window); context->window = NULL; } - context->window = newwin (/* height = */ 4, + context->window = newwin (/* height = */ 5, /* width = */ width, - /* y = */ main_win_height + (4 * context->index), + /* y = */ main_win_height + (5 * context->index), /* x = */ 0); } @@ -967,7 +1142,7 @@ static void update_host_hook (pingobj_iter_t *iter, /* {{{ */ } #if USE_NCURSES - update_stats_from_context (context); + update_stats_from_context (context, iter); wrefresh (main_win); #endif } /* }}} void update_host_hook */ @@ -1058,6 +1233,7 @@ int main (int argc, char **argv) /* {{{ */ } #endif + setlocale(LC_ALL, ""); optind = read_options (argc, argv); #if !_POSIX_SAVED_IDS @@ -1262,7 +1438,12 @@ int main (int argc, char **argv) /* {{{ */ return (1); } - if (ping_send (ping) < 0) + status = ping_send (ping); + if (status == -EINTR) + { + continue; + } + else if (status < 0) { fprintf (stderr, "ping_send failed: %s\n", ping_get_error (ping)); @@ -1295,14 +1476,13 @@ int main (int argc, char **argv) /* {{{ */ /* printf ("Sleeping for %i.%09li seconds\n", (int) ts_wait.tv_sec, ts_wait.tv_nsec); */ while ((status = nanosleep (&ts_wait, &ts_wait)) != 0) { - if (errno != EINTR) + if (errno == EINTR) { - perror ("nanosleep"); - break; + continue; } - else if (opt_count == 0) + else { - /* sigint */ + perror ("nanosleep"); break; } }