Ethereal-dev: [Ethereal-dev] [PATCH] export data as CSV for iostat
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: francesco fondelli <fondelli.francesco@xxxxxxxxxx>
Date: Fri, 29 Oct 2004 11:47:39 +0200
Hi all, I needed a way to plot rate graph nicer than IO-Stat does, so I wrote a patch that exports data in a CSV formatted file. So we can now plot an io graph using gnuplot, Excel... I tested the patch against the svn version of ethereal, compiled for GNU/Linux with gtk2. Hope this is useful for someone else. I tried to follow Ronnie Sahlberg's coding style for names and indentation. Please find attached the "svn-diffed" patch. Ciao FF
Index: AUTHORS
===================================================================
--- AUTHORS (revision 12430)
+++ AUTHORS (working copy)
@@ -2226,6 +2226,7 @@
Francesco Fondelli <fondelli.francesco [AT] tiscali.it> {
ICE protocol support
+ IO-Stat: added support for data export as csv
}
Index: gtk/io_stat.c
===================================================================
--- gtk/io_stat.c (revision 12430)
+++ gtk/io_stat.c (working copy)
@@ -1,6 +1,8 @@
/* io_stat.c
* io_stat 2002 Ronnie Sahlberg
*
+ * Francesco Fondelli (_FF_), 28-Oct-2004, added support for data export as csv.
+ *
* $Id$
*
* Ethereal - Network traffic analyzer
@@ -149,6 +151,7 @@
GdkPixmap *pixmap;
GtkAdjustment *scrollbar_adjustment;
GtkWidget *scrollbar;
+ GtkWidget *save_as_w;
int pixmap_width;
int pixmap_height;
int pixels_per_tick;
@@ -1064,6 +1067,7 @@
io->pixmap=NULL;
io->scrollbar=NULL;
io->scrollbar_adjustment=NULL;
+ io->save_as_w=NULL;
io->pixmap_width=500;
io->pixmap_height=200;
io->pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK];
@@ -1864,13 +1868,170 @@
return;
}
+/* based on file_dlg.c code */
+static void
+iostat_save_as_ok_cb(GtkWidget *bt _U_, gpointer data _U_)
+{
+ io_stat_t *io = (io_stat_t *)data;
+ gchar *csvf_name;
+ FILE *fp;
+ gint32 i, j;
+ gint32 lastgraph = -1;
+ gchar *filter;
+ gchar *field;
+
+#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
+ csvf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(io->save_as_w)));
+#else
+ csvf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(io->save_as_w)));
+#endif
+
+ /* check whether the user specified a directory instead of a file */
+ if (test_for_directory(csvf_name) == EISDIR) {
+ /* It's a directory - set the file selection box to display that
+ directory, and leave the selection box displayed. */
+ set_last_open_dir(csvf_name);
+ g_free(csvf_name);
+ file_selection_set_current_folder(io->save_as_w, get_last_open_dir());
+ return;
+ }
+
+ /* it was a file, open it */
+ if ((fp = fopen(csvf_name, "w+")) == NULL) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Could not open\n%s\nfor writing: %s.",
+ csvf_name, strerror(errno));
+ g_free(csvf_name);
+ return;
+ }
+
+ /* print file header */
+
+ fprintf(fp, "################################################################################\n");
+ fprintf(fp, "# CSV file exported by Ethereal->Statistics->IO Graphs\n");
+ /* XXX to do: add Start/End time lines, i.e. the abs arrival time of the first and last pkt
+ to let the user easily remember when the measure has been taken.
+ And maybe a line telling which interface the traffic has been sniffed from.
+ */
+ fprintf(fp, "# Y Unit: %s\n", count_type_names[io->count_type]);
+ fprintf(fp, "# X Tick Interval: %dms\n", io->interval);
+ for( i = 0; i < MAX_GRAPHS; i++ )
+ if(io->graphs[i].display) {
+
+ filter = (char *)gtk_entry_get_text(GTK_ENTRY(io->graphs[i].filter_field));
+ fprintf(fp, "# Graph%d: %s", i + 1,
+ ((filter==NULL) || (filter[0]==0)) ? "all" : filter);
+
+ if ( io->count_type == COUNT_TYPE_ADVANCED ) {
+ field = (char *)gtk_entry_get_text(GTK_ENTRY(io->graphs[i].calc_field));
+ fprintf(fp, ", %s on %s\n", calc_type_names[io->graphs[i].calc_type], field);
+ } else
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "################################################################################\n");
+
+ /* find the last graph displayed */
+
+ for( i = (MAX_GRAPHS - 1); i >= 0 ; i-- )
+ if(io->graphs[i].display) {
+ lastgraph = i;
+ break;
+ }
+
+ /* save graphs data */
+
+ for( j = 0; j < (io->num_items - 1); j++ ) {
+
+ for( i = 0; i < MAX_GRAPHS; i++ ) {
+
+ /* save only displayed graphs */
+
+ if(!io->graphs[i].display)
+ continue;
+
+ /* save the point in the form it is displayed */
+
+ if ( i != lastgraph )
+ fprintf(fp, "%d,", get_it_value(io, i, j));
+ else
+ fprintf(fp, "%d\n", get_it_value(io, i, j));
+ }
+ }
+
+ fclose(fp);
+ g_free(csvf_name);
+ window_destroy(GTK_WIDGET(io->save_as_w));
+}
static void
+iostat_save_as_destroy_cb(GtkWidget *win _U_, gpointer data _U_)
+{
+ io_stat_t *io = (io_stat_t *)data;
+ io->save_as_w = NULL;
+}
+
+/* based on file_dlg.c code */
+static void
+iostat_dlg_save_as_cb(GtkWidget *bt_save _U_, gpointer data _U_)
+{
+ io_stat_t *io = (io_stat_t *)data;
+ gboolean sth_to_save = FALSE;
+ gint32 i;
+
+ /* check for something to save */
+
+ for( i = 0; i < MAX_GRAPHS; i++ )
+ if(io->graphs[i].display)
+ sth_to_save = TRUE;
+
+ if ( (!sth_to_save) || (io->num_items == 0) ) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "There is no data to save.");
+ return;
+ }
+
+ if (io->save_as_w != NULL) {
+ /* there is already a Save dialog box; reactivate it. */
+ reactivate_window(io->save_as_w);
+ return;
+ }
+
+ /* file selection from dlg_util */
+ io->save_as_w = file_selection_new("Ethereal: Save Graphs Data as CSV", FILE_SELECTION_SAVE);
+
+ SIGNAL_CONNECT(io->save_as_w, "destroy", iostat_save_as_destroy_cb, io);
+
+#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
+ if (gtk_dialog_run(GTK_DIALOG(io->save_as_w)) == GTK_RESPONSE_ACCEPT) {
+ iostat_save_as_ok_cb(io->save_as_w, io);
+ } else {
+ window_destroy(io->save_as_w);
+ }
+#else
+ /* Connect the ok_button to iostat_save_as_ok_cb function and pass along a pointer to io */
+ SIGNAL_CONNECT(GTK_FILE_SELECTION(io->save_as_w)->ok_button, "clicked",
+ iostat_save_as_ok_cb, io);
+
+ window_set_cancel_button(io->save_as_w,
+ GTK_FILE_SELECTION(io->save_as_w)->cancel_button,
+ window_cancel_button_cb);
+
+ SIGNAL_CONNECT(io->save_as_w, "delete_event", window_delete_event_cb, NULL);
+
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(io->save_as_w), "");
+
+ gtk_widget_show(io->save_as_w);
+ window_present(io->save_as_w);
+#endif
+}
+
+
+static void
init_io_stat_window(io_stat_t *io)
{
GtkWidget *vbox;
GtkWidget *hbox;
- GtkWidget *bt_close;
+ GtkWidget *bt_close;
+ GtkWidget *bt_save;
/* create the main window */
io->window=window_new(GTK_WINDOW_TOPLEVEL, "I/O Graphs");
@@ -1883,7 +2044,7 @@
hbox=gtk_hbox_new(FALSE, 3);
gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
- gtk_container_border_width(GTK_CONTAINER(hbox), 3);
+ gtk_container_border_width(GTK_CONTAINER(hbox), 3);
gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_show(hbox);
@@ -1892,17 +2053,20 @@
io_stat_set_title(io);
- hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ hbox = dlg_button_row_new(GTK_STOCK_SAVE, GTK_STOCK_CLOSE, NULL);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show(hbox);
+ gtk_widget_show(hbox);
+
+ bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
+ window_set_cancel_button(io->window, bt_close, window_cancel_button_cb);
+
+ bt_save = OBJECT_GET_DATA(hbox, GTK_STOCK_SAVE);
+ SIGNAL_CONNECT(bt_save, "clicked", iostat_dlg_save_as_cb, io);
- bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
- window_set_cancel_button(io->window, bt_close, window_cancel_button_cb);
-
- SIGNAL_CONNECT(io->window, "delete_event", window_delete_event_cb, NULL);
-
- gtk_widget_show(io->window);
- window_present(io->window);
+ SIGNAL_CONNECT(io->window, "delete_event", window_delete_event_cb, NULL);
+
+ gtk_widget_show(io->window);
+ window_present(io->window);
}
- Follow-Ups:
- Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- From: ronnie sahlberg
- Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Prev by Date: Re: [Ethereal-dev] Patch to packet-http.c - Authentication 'Negotiate' can also be GSSAPI, not just NTLMSSP
- Next by Date: Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Previous by thread: Re: [Ethereal-dev] Reassembling out of order packets
- Next by thread: Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Index(es):





