"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/oping.c" between
liboping-1.9.0.tar.gz and liboping-1.10.0.tar.gz

About: liboping is a C library to generate ICMP echo requests, better known as "ping packets". It can "ping" multiple hosts in parallel using IPv4 or IPv6 transparently. A commandline and a ncurses-based application are included.

oping.c  (liboping-1.9.0):oping.c  (liboping-1.10.0)
/** /**
* Object oriented C module to send ICMP and ICMPv6 `echo's. * Object oriented C module to send ICMP and ICMPv6 `echo's.
* Copyright (C) 2006-2016 Florian octo Forster <ff at octo.it> * Copyright (C) 2006-2017 Florian octo Forster <ff at octo.it>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; only version 2 of the License is * the Free Software Foundation; only version 2 of the License is
* applicable. * applicable.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 85 skipping to change at line 85
#endif #endif
#include <locale.h> #include <locale.h>
#include <langinfo.h> #include <langinfo.h>
#if USE_NCURSES #if USE_NCURSES
# define NCURSES_OPAQUE 1 # define NCURSES_OPAQUE 1
/* http://newsgroups.derkeiler.com/Archive/Rec/rec.games.roguelike.development/2 010-09/msg00050.html */ /* http://newsgroups.derkeiler.com/Archive/Rec/rec.games.roguelike.development/2 010-09/msg00050.html */
# define _X_OPEN_SOURCE_EXTENDED # define _X_OPEN_SOURCE_EXTENDED
# if HAVE_NCURSESW_NCURSES_H #if defined HAVE_NCURSESW_CURSES_H
# include <ncursesw/ncurses.h> # include <ncursesw/curses.h>
# elif HAVE_NCURSES_H #elif defined HAVE_NCURSESW_H
# include <ncursesw.h>
#elif defined HAVE_NCURSES_CURSES_H
# include <ncurses/curses.h>
#elif defined HAVE_NCURSES_H
# include <ncurses.h> # include <ncurses.h>
# endif #else
# error "SysV or X/Open-compatible Curses header file required"
#endif
# define OPING_GREEN 1 # define OPING_GREEN 1
# define OPING_YELLOW 2 # define OPING_YELLOW 2
# define OPING_RED 3 # define OPING_RED 3
# define OPING_GREEN_HIST 4 # define OPING_GREEN_HIST 4
# define OPING_YELLOW_HIST 5 # define OPING_YELLOW_HIST 5
# define OPING_RED_HIST 6 # define OPING_RED_HIST 6
double const threshold_green = 0.8; double const threshold_green = 0.8;
double const threshold_yellow = 0.95; double const threshold_yellow = 0.95;
skipping to change at line 175 skipping to change at line 181
#ifndef HISTORY_SIZE_MAX #ifndef HISTORY_SIZE_MAX
# define HISTORY_SIZE_MAX 900 # define HISTORY_SIZE_MAX 900
#endif #endif
/* The last n RTTs in the order they were sent. */ /* The last n RTTs in the order they were sent. */
double history_by_time[HISTORY_SIZE_MAX]; double history_by_time[HISTORY_SIZE_MAX];
/* Current number of entries in the history. This is a value between 0 /* Current number of entries in the history. This is a value between 0
* and HISTORY_SIZE_MAX. */ * and HISTORY_SIZE_MAX. */
size_t history_size; size_t history_size;
/* Number "received" entries in the history, i.e. non-NAN entries. */ /* Total number of reponses received. */
size_t history_received; size_t history_received;
/* Index of the next RTT to be written to history_by_time. This wraps /* Index of the next RTT to be written to history_by_time. This wraps
* around to 0 once the histroty has grown to HISTORY_SIZE_MAX. */ * around to 0 once the histroty has grown to HISTORY_SIZE_MAX. */
size_t history_index; size_t history_index;
/* The last history_size RTTs sorted by value. timed out packets (NAN /* The last history_size RTTs sorted by value. timed out packets (NAN
* entries) are sorted to the back. */ * entries) are sorted to the back. */
double history_by_value[HISTORY_SIZE_MAX]; double history_by_value[HISTORY_SIZE_MAX];
skipping to change at line 212 skipping to change at line 218
static int opt_send_ttl = 64; static int opt_send_ttl = 64;
static uint8_t opt_send_qos = 0; static uint8_t opt_send_qos = 0;
#define OPING_DEFAULT_PERCENTILE 95.0 #define OPING_DEFAULT_PERCENTILE 95.0
static double opt_percentile = -1.0; static double opt_percentile = -1.0;
static double opt_exit_status_threshold = 1.0; static double opt_exit_status_threshold = 1.0;
#if USE_NCURSES #if USE_NCURSES
static int opt_show_graph = 1; static int opt_show_graph = 1;
static int opt_utf8 = 0; static int opt_utf8 = 0;
#endif #endif
static char *opt_outfile = NULL; static char *opt_outfile = NULL;
static int opt_bell = 0;
static int host_num = 0; static int host_num = 0;
static FILE *outfile = NULL; static FILE *outfile = NULL;
#if USE_NCURSES #if USE_NCURSES
static WINDOW *main_win = NULL; static WINDOW *main_win = NULL;
#endif #endif
static void sigint_handler (int signal) /* {{{ */ static void sigint_handler (int signal) /* {{{ */
{ {
/* Make compiler happy */ /* Make compiler happy */
signal = 0; signal = 0;
/* Exit the loop */ /* Exit the loop */
opt_count = 0; opt_count = 0;
} /* }}} void sigint_handler */ } /* }}} void sigint_handler */
static ping_context_t *context_create (void) /* {{{ */ static ping_context_t *context_create () /* {{{ */
{ {
ping_context_t *ret; ping_context_t *ctx = calloc (1, sizeof (*ctx));
if (ctx == NULL)
if ((ret = malloc (sizeof (ping_context_t))) == NULL)
return (NULL); return (NULL);
memset (ret, '\0', sizeof (ping_context_t));
ret->latency_total = 0.0;
#if USE_NCURSES #if USE_NCURSES
ret->window = NULL; ctx->window = NULL;
#endif #endif
return (ret); return (ctx);
} /* }}} ping_context_t *context_create */ } /* }}} ping_context_t *context_create */
static void context_destroy (ping_context_t *context) /* {{{ */ static void context_destroy (ping_context_t *context) /* {{{ */
{ {
if (context == NULL) if (context == NULL)
return; return;
#if USE_NCURSES #if USE_NCURSES
if (context->window != NULL) if (context->window != NULL)
{ {
skipping to change at line 295 skipping to change at line 297
{ {
size_t i; size_t i;
if (!ctx->history_dirty) if (!ctx->history_dirty)
return; return;
/* Copy all values from by_time to by_value. */ /* Copy all values from by_time to by_value. */
memcpy (ctx->history_by_value, ctx->history_by_time, memcpy (ctx->history_by_value, ctx->history_by_time,
sizeof (ctx->history_by_time)); sizeof (ctx->history_by_time));
/* Remove impossible values caused by adding a new host */
for (i = 0; i < ctx->history_size; i++)
if (ctx->history_by_value[i] < 0)
ctx->history_by_value[i] = NAN;
/* Sort all RTTs. */ /* Sort all RTTs. */
qsort (ctx->history_by_value, ctx->history_size, sizeof qsort (ctx->history_by_value, ctx->history_size, sizeof
(ctx->history_by_value[0]), compare_double); (ctx->history_by_value[0]), compare_double);
/* Update the number of received RTTs. */ /* Update the number of received RTTs. */
ctx->history_received = 0; ctx->history_received = 0;
for (i = 0; i < ctx->history_size; i++) for (i = 0; i < ctx->history_size; i++)
if (!isnan (ctx->history_by_value[i])) if (!isnan (ctx->history_by_value[i]))
ctx->history_received++; ctx->history_received++;
skipping to change at line 399 skipping to change at line 406
return (0.0); return (0.0);
return (100.0 * (ctx->req_sent - ctx->req_rcvd) return (100.0 * (ctx->req_sent - ctx->req_rcvd)
/ ((double) ctx->req_sent)); / ((double) ctx->req_sent));
} /* }}} double context_get_packet_loss */ } /* }}} double context_get_packet_loss */
static int ping_initialize_contexts (pingobj_t *ping) /* {{{ */ static int ping_initialize_contexts (pingobj_t *ping) /* {{{ */
{ {
pingobj_iter_t *iter; pingobj_iter_t *iter;
int index; int index;
size_t history_size = 0;
if (ping == NULL) if (ping == NULL)
return (EINVAL); return (EINVAL);
index = 0; index = 0;
for (iter = ping_iterator_get (ping); for (iter = ping_iterator_get (ping);
iter != NULL; iter != NULL;
iter = ping_iterator_next (iter)) iter = ping_iterator_next (iter))
{ {
ping_context_t *context; ping_context_t *context;
size_t buffer_size; size_t buffer_size;
int i;
context = ping_iterator_get_context(iter);
/* if this is a previously existing host, do not recreate it */
if (context != NULL)
{
history_size = context->history_size;
context->index = index++;
continue;
}
context = context_create (); context = context_create ();
context->index = index; context->index = index;
/* start new hosts at the same graph point as old hosts */
context->history_size = history_size;
context->history_index = history_size;
for (i = 0; i < history_size; i++)
context->history_by_time[i] = -1;
buffer_size = sizeof (context->host); buffer_size = sizeof (context->host);
ping_iterator_get_info (iter, PING_INFO_HOSTNAME, context->host, &buffer_size); ping_iterator_get_info (iter, PING_INFO_HOSTNAME, context->host, &buffer_size);
buffer_size = sizeof (context->addr); buffer_size = sizeof (context->addr);
ping_iterator_get_info (iter, PING_INFO_ADDRESS, context->addr, & buffer_size); ping_iterator_get_info (iter, PING_INFO_ADDRESS, context->addr, & buffer_size);
ping_iterator_set_context (iter, (void *) context); ping_iterator_set_context (iter, (void *) context);
index++; index++;
} }
skipping to change at line 655 skipping to change at line 680
return (buffer); return (buffer);
} /* }}} char *format_qos */ } /* }}} char *format_qos */
static int read_options (int argc, char **argv) /* {{{ */ static int read_options (int argc, char **argv) /* {{{ */
{ {
int optchar; int optchar;
while (1) while (1)
{ {
optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:O:P:m:w:" optchar = getopt (argc, argv, "46c:hi:I:t:Q:f:D:Z:O:P:m:w:b"
#if USE_NCURSES #if USE_NCURSES
"uUg:" "uUg:"
#endif #endif
); );
if (optchar == -1) if (optchar == -1)
break; break;
switch (optchar) switch (optchar)
{ {
skipping to change at line 757 skipping to change at line 782
case 'Q': case 'Q':
set_opt_send_qos (optarg); set_opt_send_qos (optarg);
break; break;
case 'O': case 'O':
{ {
free (opt_outfile); free (opt_outfile);
opt_outfile = strdup (optarg); opt_outfile = strdup (optarg);
} }
break;
case 'P': case 'P':
{ {
double new_percentile; double new_percentile;
new_percentile = atof (optarg); new_percentile = atof (optarg);
if (isnan (new_percentile) if (isnan (new_percentile)
|| (new_percentile < 0.1) || (new_percentile < 0.1)
|| (new_percentile > 100. 0)) || (new_percentile > 100. 0))
fprintf (stderr, "Ignoring invali d percentile: %s\n", fprintf (stderr, "Ignoring invali d percentile: %s\n",
optarg); optarg);
skipping to change at line 793 skipping to change at line 819
fprintf (stderr, "Unknown graph option: % s\n", optarg); fprintf (stderr, "Unknown graph option: % s\n", optarg);
break; break;
case 'u': case 'u':
opt_utf8 = 2; opt_utf8 = 2;
break; break;
case 'U': case 'U':
opt_utf8 = 1; opt_utf8 = 1;
break; break;
#endif #endif
case 'b':
opt_bell = 1;
break;
case 'Z': case 'Z':
{ {
char *endptr = NULL; char *endptr = NULL;
double tmp; double tmp;
errno = 0; errno = 0;
tmp = strtod (optarg, &endptr); tmp = strtod (optarg, &endptr);
if ((errno != 0) || (endptr == NULL) || (*endptr != 0) || (tmp < 0.0) || (tmp > 100.0)) if ((errno != 0) || (endptr == NULL) || (*endptr != 0) || (tmp < 0.0) || (tmp > 100.0))
{ {
skipping to change at line 997 skipping to change at line 1026
if (reverse) if (reverse)
wattroff (ctx->window, A_REVERSE); wattroff (ctx->window, A_REVERSE);
} }
free (counters); free (counters);
free (ratios); free (ratios);
return (0); return (0);
} /* }}} int update_graph_boxplot */ } /* }}} int update_graph_boxplot */
static int update_graph_prettyping (ping_context_t *ctx, /* {{{ */ static int update_graph_prettyping (ping_context_t *ctx, /* {{{ */
double latency, unsigned int sequence) double latency)
{ {
size_t x; size_t x;
size_t x_max; size_t x_max;
size_t history_offset; size_t history_offset;
x_max = (size_t) getmaxx (ctx->window); x_max = (size_t) getmaxx (ctx->window);
if (x_max <= 4) if (x_max <= 4)
return (EINVAL); return (EINVAL);
x_max -= 4; x_max -= 4;
skipping to change at line 1044 skipping to change at line 1073
if (x >= ctx->history_size) if (x >= ctx->history_size)
{ {
mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2, ' ') ; mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2, ' ') ;
continue; continue;
} }
index = (history_offset + x) % ctx->history_size; index = (history_offset + x) % ctx->history_size;
latency = ctx->history_by_time[index]; latency = ctx->history_by_time[index];
if (latency < 0) {
continue;
}
if (latency >= 0.0) if (latency >= 0.0)
{ {
double ratio; double ratio;
size_t symbols_num = hist_symbols_acs_num; size_t symbols_num = hist_symbols_acs_num;
size_t colors_num = 1; size_t colors_num = 1;
size_t index_symbols; size_t index_symbols;
size_t index_colors; size_t index_colors;
size_t intensity; size_t intensity;
skipping to change at line 1215 skipping to change at line 1248
} /* }}} int update_graph_histogram */ } /* }}} int update_graph_histogram */
static int update_stats_from_context (ping_context_t *ctx, pingobj_iter_t *iter) /* {{{ */ static int update_stats_from_context (ping_context_t *ctx, pingobj_iter_t *iter) /* {{{ */
{ {
double latency = -1.0; double latency = -1.0;
size_t buffer_len = sizeof (latency); size_t buffer_len = sizeof (latency);
ping_iterator_get_info (iter, PING_INFO_LATENCY, ping_iterator_get_info (iter, PING_INFO_LATENCY,
&latency, &buffer_len); &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)) if ((ctx == NULL) || (ctx->window == NULL))
return (EINVAL); return (EINVAL);
/* werase (ctx->window); */ /* werase (ctx->window); */
box (ctx->window, 0, 0); box (ctx->window, 0, 0);
wattron (ctx->window, A_BOLD); wattron (ctx->window, A_BOLD);
mvwprintw (ctx->window, /* y = */ 0, /* x = */ 5, mvwprintw (ctx->window, /* y = */ 0, /* x = */ 5,
" %s ", ctx->host); " %s ", ctx->host);
wattroff (ctx->window, A_BOLD); wattroff (ctx->window, A_BOLD);
skipping to change at line 1255 skipping to change at line 1283
median = percentile_to_latency (ctx, 50.0); median = percentile_to_latency (ctx, 50.0);
max = percentile_to_latency (ctx, 100.0); max = percentile_to_latency (ctx, 100.0);
percentile = percentile_to_latency (ctx, opt_percentile); percentile = percentile_to_latency (ctx, opt_percentile);
mvwprintw (ctx->window, /* y = */ 2, /* x = */ 2, mvwprintw (ctx->window, /* y = */ 2, /* x = */ 2,
"RTT[ms]: min = %.0f, median = %.0f, p(%.0f) = %. 0f, max = %.0f ", "RTT[ms]: min = %.0f, median = %.0f, p(%.0f) = %. 0f, max = %.0f ",
min, median, opt_percentile, percentile, max); min, median, opt_percentile, percentile, max);
} }
if (opt_show_graph == 1) if (opt_show_graph == 1)
update_graph_prettyping (ctx, latency, sequence); update_graph_prettyping (ctx, latency);
else if (opt_show_graph == 2) else if (opt_show_graph == 2)
update_graph_histogram (ctx); update_graph_histogram (ctx);
else if (opt_show_graph == 3) else if (opt_show_graph == 3)
update_graph_boxplot (ctx); update_graph_boxplot (ctx);
wrefresh (ctx->window); wrefresh (ctx->window);
return (0); return (0);
} /* }}} int update_stats_from_context */ } /* }}} int update_stats_from_context */
skipping to change at line 1299 skipping to change at line 1327
iter = ping_iterator_next (iter)) iter = ping_iterator_next (iter))
{ {
ping_context_t *context; ping_context_t *context;
context = ping_iterator_get_context (iter); context = ping_iterator_get_context (iter);
if (context == NULL) if (context == NULL)
continue; continue;
if (context->window != NULL) if (context->window != NULL)
{ {
werase (context->window);
wrefresh (context->window);
delwin (context->window); delwin (context->window);
context->window = NULL; context->window = NULL;
} }
context->window = newwin (/* height = */ box_height, context->window = newwin (/* height = */ box_height,
/* width = */ width, /* width = */ width,
/* y = */ main_win_height + (box_height * context ->index), /* y = */ main_win_height + (box_height * context ->index),
/* x = */ 0); /* x = */ 0);
} }
return (0); return (0);
skipping to change at line 1329 skipping to change at line 1359
break; break;
else if (key == KEY_RESIZE) else if (key == KEY_RESIZE)
need_resize = 1; need_resize = 1;
else if (key == 'g') else if (key == 'g')
{ {
if (opt_show_graph == 3) if (opt_show_graph == 3)
opt_show_graph = 1; opt_show_graph = 1;
else if (opt_show_graph > 0) else if (opt_show_graph > 0)
opt_show_graph++; opt_show_graph++;
} }
else if (key == 'a')
{
char host[NI_MAXHOST];
wprintw (main_win, "New Host: ");
echo ();
wgetnstr (main_win, host, sizeof (host));
noecho ();
if (ping_host_add(ping, host) < 0)
{
const char *errmsg = ping_get_error (ping);
wprintw (main_win, "Adding host `%s' failed: %s\n
", host, errmsg);
}
else
{
/* FIXME - scroll main_win correctly so that old
* data is still visible */
need_resize = 1;
host_num = ping_iterator_count(ping);
ping_initialize_contexts(ping);
}
}
} }
if (need_resize) if (need_resize)
return (on_resize (ping)); return (on_resize (ping));
else else
return (0); return (0);
} /* }}} int check_resize */ } /* }}} int check_resize */
static int pre_loop_hook (pingobj_t *ping) /* {{{ */ static int pre_loop_hook (pingobj_t *ping) /* {{{ */
{ {
skipping to change at line 1357 skipping to change at line 1411
noecho (); noecho ();
nodelay (stdscr, TRUE); nodelay (stdscr, TRUE);
getmaxyx (stdscr, height, width); getmaxyx (stdscr, height, width);
if ((height < 1) || (width < 1)) if ((height < 1) || (width < 1))
return (EINVAL); return (EINVAL);
if (has_colors () == TRUE) if (has_colors () == TRUE)
{ {
start_color (); start_color ();
init_pair (OPING_GREEN, COLOR_GREEN, /* default = */ 0); use_default_colors ();
init_pair (OPING_YELLOW, COLOR_YELLOW, /* default = */ 0); init_pair (OPING_GREEN, COLOR_GREEN, /* default = */ -1);
init_pair (OPING_RED, COLOR_RED, /* default = */ 0); init_pair (OPING_YELLOW, COLOR_YELLOW, /* default = */ -1);
init_pair (OPING_GREEN_HIST, COLOR_GREEN, COLOR_BLACK); init_pair (OPING_RED, COLOR_RED, /* default = */ -1);
init_pair (OPING_GREEN_HIST, COLOR_GREEN, -1);
init_pair (OPING_YELLOW_HIST, COLOR_YELLOW, COLOR_GREEN); init_pair (OPING_YELLOW_HIST, COLOR_YELLOW, COLOR_GREEN);
init_pair (OPING_RED_HIST, COLOR_RED, COLOR_YELLOW); init_pair (OPING_RED_HIST, COLOR_RED, COLOR_YELLOW);
} }
main_win_height = height - (box_height * host_num); main_win_height = height - (box_height * host_num);
main_win = newwin (/* height = */ main_win_height, main_win = newwin (/* height = */ main_win_height,
/* width = */ width, /* width = */ width,
/* y = */ 0, /* x = */ 0); /* y = */ 0, /* x = */ 0);
/* Allow scrolling */ /* Allow scrolling */
scrollok (main_win, TRUE); scrollok (main_win, TRUE);
skipping to change at line 1576 skipping to change at line 1631
sequence, recv_ttl); sequence, recv_ttl);
if ((recv_qos != 0) || (opt_send_qos != 0)) if ((recv_qos != 0) || (opt_send_qos != 0))
{ {
HOST_PRINTF ("qos=%s ", HOST_PRINTF ("qos=%s ",
format_qos (recv_qos, recv_qos_str, sizeo f (recv_qos_str))); format_qos (recv_qos, recv_qos_str, sizeo f (recv_qos_str)));
} }
HOST_PRINTF ("time=%.2f ms\n", latency); HOST_PRINTF ("time=%.2f ms\n", latency);
#if USE_NCURSES #if USE_NCURSES
} }
#endif #endif
if (opt_bell) {
#if USE_NCURSES
beep();
#else
HOST_PRINTF ("\a");
#endif
}
} }
else /* if (!(latency > 0.0)) */ else /* if (!(latency > 0.0)) */
{ {
#if USE_NCURSES #if USE_NCURSES
if (has_colors () == TRUE) if (has_colors () == TRUE)
{ {
HOST_PRINTF ("echo reply from %s (%s): icmp_seq=%u ", HOST_PRINTF ("echo reply from %s (%s): icmp_seq=%u ",
context->host, context->addr, context->host, context->addr,
sequence); sequence);
wattron (main_win, COLOR_PAIR(OPING_RED) | A_BOLD); wattron (main_win, COLOR_PAIR(OPING_RED) | A_BOLD);
skipping to change at line 1603 skipping to change at line 1665
HOST_PRINTF ("echo reply from %s (%s): icmp_seq=%u timeout\n", HOST_PRINTF ("echo reply from %s (%s): icmp_seq=%u timeout\n",
context->host, context->addr, context->host, context->addr,
sequence); sequence);
#if USE_NCURSES #if USE_NCURSES
} }
#endif #endif
} }
if (outfile != NULL) if (outfile != NULL)
{ {
struct timespec ts = { 0, 0 }; struct timeval tv = {0};
if (gettimeofday (&tv, NULL) == 0)
if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
{ {
double t = ((double) ts.tv_sec) + (((double) ts.tv_nsec) / 1000000000.0); double t = ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1000000.0);
if ((sequence % 32) == 0) if ((sequence % 32) == 0)
fprintf (outfile, "#time,host,latency[ms]\n"); fprintf (outfile, "#time,host,latency[ms]\n");
fprintf (outfile, "%.3f,\"%s\",%.2f\n", t, context->host, latency); fprintf (outfile, "%.3f,\"%s\",%.2f\n", t, context->host, latency);
} }
} }
#if USE_NCURSES #if USE_NCURSES
update_stats_from_context (context, iter); update_stats_from_context (context, iter);
 End of changes. 27 change blocks. 
32 lines changed or deleted 94 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS