/* ethereal.c
*
- * $Id: ethereal.c,v 1.49 1999/07/07 23:54:12 guy Exp $
+ * $Id: ethereal.c,v 1.108 1999/08/26 06:20:49 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* - Playback window
* - Multiple window support
* - Add cut/copy/paste
- * - Fix progress/status bar glitches? (GTK+ bug?)
* - Create header parsing routines
* - Check fopens, freads, fwrites
* - Make byte view scrollbars automatic?
#endif
#include <gtk/gtk.h>
-#include <pcap.h> /* needed for capture.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
+
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
+
#include <signal.h>
#ifdef NEED_SNPRINTF_H
#include "summary.h"
#include "file.h"
#include "menu.h"
-#include "etypes.h"
#include "prefs.h"
#include "column.h"
#include "print.h"
#include "gtkpacket.h"
#include "dfilter.h"
+static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
static void file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs);
static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
+static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
+static void print_file_cb(GtkWidget *file_bt, gpointer file_te);
+static void print_fs_ok_cb(GtkWidget *w, gpointer data);
+static void print_fs_cancel_cb(GtkWidget *w, gpointer data);
+static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
+static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
FILE *data_out_file = NULL;
packet_info pi;
capture_file cf;
-proto_tree *protocol_tree = NULL;
GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
*info_bar;
GdkFont *m_r_font, *m_b_font;
-GtkStyle *pl_style;
guint main_ctx, file_ctx;
-frame_data *fd;
gint start_capture = 0;
gchar comp_info_str[256];
gchar *ethereal_path = NULL;
gchar *medium_font = MONO_MEDIUM_FONT;
gchar *bold_font = MONO_BOLD_FONT;
+gchar *last_open_dir = NULL;
ts_type timestamp_type = RELATIVE;
GtkStyle *item_style;
+#ifdef HAVE_LIBPCAP
int sync_mode; /* allow sync */
int sync_pipe[2]; /* used to sync father */
int fork_mode; /* fork a child to do the capture */
int sigusr2_received = 0;
int quit_after_cap; /* Makes a "capture only mode". Implies -k */
+#endif
/* Specifies byte offsets for object selected in tree */
static gint tree_selected_start=-1, tree_selected_len=-1;
#define E_DFILTER_TE_KEY "display_filter_te"
+#define E_RFILTER_TE_KEY "read_filter_te"
/* About Ethereal window */
void
"Ashok Narayanan <ashokn@cisco.com>\n"
"Aaron Hillegass <aaron@classmax.com>\n"
"Jason Lango <jal@netapp.com>\n"
+ "Johan Feyaerts <Johan.Feyaerts@siemens.atea.be>\n"
+ "Olivier Abad <abad@daba.dhis.org>\n"
+ "Thierry Andry <Thierry.Andry@advalvas.be>\n"
+ "Jeff Foster <jfoste@woodward.com>\n"
"\nSee http://ethereal.zing.org for more information",
VERSION, comp_info_str);
}
-/* Things to do when the OK button is pressed */
-void
-file_sel_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
- gchar *cf_name;
- int err;
-
- cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
- gtk_widget_hide(GTK_WIDGET (fs));
- gtk_widget_destroy(GTK_WIDGET (fs));
-
- /* this depends upon load_cap_file removing the filename from
- * cf_name, leaving only the path to the directory. */
- if ((err = load_cap_file(cf_name, &cf)) == 0)
- chdir(cf_name);
- else {
- simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
- cf_name);
- }
- g_free(cf_name);
-#ifdef USE_ITEM
- set_menu_sensitivity("/File/Save", FALSE);
- set_menu_sensitivity("/File/Save As...", TRUE);
- set_menu_sensitivity("/Tools/Summary", TRUE);
-#else
- set_menu_sensitivity("<Main>/File/Save", FALSE);
- set_menu_sensitivity("<Main>/File/Save As...", TRUE);
- set_menu_sensitivity("<Main>/Tools/Summary", TRUE);
-#endif
-}
-
/* Update the progress bar */
gint
file_progress_cb(gpointer p) {
+ capture_file *cf = (capture_file*) p;
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
- (gfloat) ftell(cf.fh) / (gfloat) cf.f_len);
+ (gfloat) ftell(cf->fh) / (gfloat) cf->f_len);
return TRUE;
}
-/* Follow a TCP stream */
+/* Follow the TCP stream, if any, to which the last packet that we called
+ a dissection routine on belongs (this might be the most recently
+ selected packet, or it might be the last packet in the file). */
void
follow_stream_cb( GtkWidget *w, gpointer data ) {
- char filename1[128];
+ char filename1[128+1];
GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
- GtkWidget *filter_te = NULL;
- int err;
-
- if (w)
- filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
+ int tmp_fd;
if( pi.ipproto == 6 ) {
/* we got tcp so we can follow */
- /* check to see if we are using a filter */
- if( cf.dfilter != NULL ) {
- /* get rid of this one */
- g_free( cf.dfilter );
- cf.dfilter = NULL;
+ /* Create a temporary file into which to dump the reassembled data
+ from the TCP stream, and set "data_out_file" to refer to it, so
+ that the TCP code will write to it.
+
+ XXX - it might be nicer to just have the TCP code directly
+ append stuff to the text widget for the TCP stream window,
+ if we can arrange that said window not pop up until we're
+ done. */
+ tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
+ if (tmp_fd == -1) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Could not create temporary file %s: %s", filename1, strerror(errno));
+ return;
}
- /* create a new one and set the display filter entry accordingly */
- cf.dfilter = build_follow_filter( &pi );
- if (filter_te)
- gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
- /* reload so it goes in effect. Also we set data_out_file which
- tells the tcp code to output the data */
- close_cap_file( &cf, info_bar, file_ctx);
- strcpy( filename1, tmpnam(NULL) );
- data_out_file = fopen( filename1, "a" );
+ data_out_file = fdopen( tmp_fd, "w" );
if( data_out_file == NULL ) {
- fprintf( stderr, "Could not open tmp file %s\n", filename1 );
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Could not create temporary file %s: %s", filename1, strerror(errno));
+ close(tmp_fd);
+ unlink(filename1);
+ return;
}
+
+ /* Create a new filter that matches all packets in the TCP stream,
+ and set the display filter entry accordingly */
reset_tcp_reassembly();
- err = load_cap_file( cf.filename, &cf );
- if (err != 0) {
- simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
- cf.filename);
- }
+ cf.dfilter = build_follow_filter( &pi );
+
+ /* Run the display filter so it goes in effect. */
+ filter_packets(&cf);
+
/* the data_out_file should now be full of the streams information */
fclose( data_out_file );
+
/* the filename1 file now has all the text that was in the session */
streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_widget_set_name( streamwindow, "TCP stream window" );
}
gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
+
/* setup the container */
box = gtk_vbox_new( FALSE, 0 );
gtk_container_add( GTK_CONTAINER(streamwindow), box );
gtk_widget_show( box );
+
/* set up the table we attach to */
table = gtk_table_new( 1, 2, FALSE );
gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
gtk_widget_show( table );
+
/* create a text box */
text = gtk_text_new( NULL, NULL );
gtk_text_set_editable( GTK_TEXT(text), FALSE);
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
gtk_widget_show(text);
+
/* create the scrollbar */
vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
gtk_widget_show( vscrollbar );
gtk_widget_realize( text );
+
/* stop the updates while we fill the text box */
gtk_text_freeze( GTK_TEXT(text) );
- data_out_file = NULL;
data_out_file = fopen( filename1, "r" );
if( data_out_file ) {
char buffer[1024];
break;
}
}
+ if( ferror( data_out_file ) ) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Error reading temporary file %s: %s", filename1, strerror(errno));
+ }
fclose( data_out_file );
- unlink( filename1 );
+ } else {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Could not open temporary file %s: %s", filename1, strerror(errno));
}
gtk_text_thaw( GTK_TEXT(text) );
+ unlink( filename1 );
data_out_file = NULL;
gtk_widget_show( streamwindow );
- if( cf.dfilter != NULL ) {
- g_free( cf.dfilter );
- cf.dfilter = NULL;
- }
} else {
simple_dialog(ESD_TYPE_WARN, NULL,
"Error following stream. Please make\n"
void
match_selected_cb(GtkWidget *w, gpointer data)
{
-#if 0
- char *buf = malloc(1024);
-#endif
+ char *buf = g_malloc(1024);
GtkWidget *filter_te = NULL;
+ char *ptr;
+ int i;
+ guint8 *c;
- if (w)
- filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
+ filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
if (tree_selected_start<0) {
simple_dialog(ESD_TYPE_WARN, NULL,
"view to be matched.");
return;
}
-#if 0
- switch (cf.lnk_t) {
- case DLT_EN10MB :
- c="ether";
- break;
- case DLT_FDDI :
- c="fddi";
- break;
- default :
-#endif
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Unsupported frame type format. Only Ethernet and FDDI\n"
- "frame formats are supported.");
- return;
-#if 0
- }
- sprintf(buf, "("); ptr = buf+strlen(buf);
- for (i=0, c=cf.pd+tree_selected_start; i+4<tree_selected_len; i+=4, c+=4) {
- sprintf(ptr, "(ether[%d : 4]=0x%02X%02X%02X%02X) and ",
- tree_selected_start+i,
- *c,
- *(c+1),
- *(c+2),
- *(c+3));
- ptr = buf+strlen(buf);
- }
+ c = cf.pd + tree_selected_start;
+ ptr = buf;
- sprintf(ptr, "(ether[%d : %d]=0x",
- tree_selected_start+i,
- tree_selected_len - i);
+ sprintf(ptr, "frame[%d : %d] == ", tree_selected_start, tree_selected_len);
ptr = buf+strlen(buf);
- for (;i<tree_selected_len; i++) {
- sprintf(ptr, "%02X", *c++);
- ptr = buf+strlen(buf);
- }
- sprintf(ptr, "))");
+ if (tree_selected_len == 1) {
+ sprintf(ptr, "0x%02x", *c++);
+ }
+ else {
+ for (i=0;i<tree_selected_len; i++) {
+ if (i == 0 ) {
+ sprintf(ptr, "%02x", *c++);
+ }
+ else {
+ sprintf(ptr, ":%02x", *c++);
+ }
+ ptr = buf+strlen(buf);
+ }
+ }
if( cf.dfilter != NULL ) {
/* get rid of this one */
g_free( cf.dfilter );
- cf.dfilter = NULL;
}
/* create a new one and set the display filter entry accordingly */
cf.dfilter = buf;
- if (filter_te)
+ if (filter_te) {
gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
- /* reload so it goes in effect. */
- close_cap_file( &cf, info_bar, file_ctx);
- load_cap_file( cf.filename, &cf );
- if( cf.dfilter != NULL ) {
- g_free( cf.dfilter );
- cf.dfilter = NULL;
}
-#endif
+ /* Run the display filter so it goes in effect. */
+ filter_packets(&cf);
}
/* Open a file */
void
file_open_cmd_cb(GtkWidget *w, gpointer data) {
+ GtkWidget *filter_hbox, *filter_bt, *filter_te;
+
+ if (last_open_dir)
+ chdir(last_open_dir);
+
file_sel = gtk_file_selection_new ("Ethereal: Open Capture File");
- /* Connect the ok_button to file_ok_sel_cb function and pass along the
- pointer to the filter entry */
+ /* Connect the ok_button to file_open_ok_cb function and pass along a
+ pointer to the file selection box widget */
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
- "clicked", (GtkSignalFunc) file_sel_ok_cb, file_sel );
+ "clicked", (GtkSignalFunc) file_open_ok_cb, file_sel );
- /* Gilbert --- I added this if statement. Is this right? */
- if (w)
gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
- E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
+ E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
+
+ filter_hbox = gtk_hbox_new(FALSE, 1);
+ gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
+ gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_sel)->action_area),
+ filter_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(filter_hbox);
+
+ filter_bt = gtk_button_new_with_label("Filter:");
+ gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
+ GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
+ gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
+ gtk_widget_show(filter_bt);
+
+ filter_te = gtk_entry_new();
+ gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
+ gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
+ gtk_widget_show(filter_te);
+
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
+ E_RFILTER_TE_KEY, filter_te);
/* Connect the cancel_button to destroy the widget */
gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
(file_sel)->cancel_button), "clicked", (GtkSignalFunc)
gtk_widget_destroy, GTK_OBJECT (file_sel));
+#ifdef HAVE_LIBPCAP
if( fork_mode && (cf.save_file != NULL) )
+#else
+ if( cf.save_file != NULL )
+#endif
gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), cf.save_file);
else
gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
gtk_widget_show(file_sel);
}
+static void
+file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
+ gchar *cf_name, *rfilter, *s;
+ GtkWidget *filter_te;
+ dfilter *rfcode = NULL;
+ int err;
+
+ cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
+ filter_te = gtk_object_get_data(GTK_OBJECT(w), E_RFILTER_TE_KEY);
+ rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
+ if (rfilter[0] != '\0') {
+ rfcode = dfilter_new();
+ if (dfilter_compile(rfcode, rfilter) != 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+ dfilter_destroy(rfcode);
+ return;
+ }
+ }
+
+ /* Try to open the capture file. */
+ if ((err = open_cap_file(cf_name, &cf)) != 0) {
+ /* We couldn't open it; don't dismiss the open dialog box,
+ just leave it around so that the user can, after they
+ dismiss the alert box popped up for the open error,
+ try again. */
+ if (rfcode != NULL)
+ dfilter_destroy(rfcode);
+ return;
+ }
+
+ /* Attach the new read filter to "cf" ("open_cap_file()" succeeded, so
+ it closed the previous capture file, and thus destroyed any
+ previous read filter attached to "cf"). */
+ cf.rfcode = rfcode;
+
+ /* We've crossed the Rubicon; get rid of the file selection box. */
+ gtk_widget_hide(GTK_WIDGET (fs));
+ gtk_widget_destroy(GTK_WIDGET (fs));
+
+ err = read_cap_file(&cf);
+ /* Save the directory name; we can write over cf_name. */
+ s = strrchr(cf_name, '/');
+ if (s && last_open_dir) {
+ *s = '\0';
+ if (strcmp(last_open_dir, cf_name) != 0) {
+ g_free(last_open_dir);
+ last_open_dir = g_strdup(cf_name);
+ }
+ }
+ else if (s) { /* ! last_open_dir */
+ *s = '\0';
+ last_open_dir = g_strdup(cf_name);
+ }
+ else {
+ last_open_dir = NULL;
+ }
+ set_menu_sensitivity("/File/Save", FALSE);
+ set_menu_sensitivity("/File/Save As...", TRUE);
+ g_free(cf_name);
+}
+
/* Close a file */
void
file_close_cmd_cb(GtkWidget *widget, gpointer data) {
close_cap_file(&cf, info_bar, file_ctx);
-#ifdef USE_ITEM
- set_menu_sensitivity("/File/Close", FALSE);
- set_menu_sensitivity("/File/Reload", FALSE);
- set_menu_sensitivity("/Tools/Summary", FALSE);
-#else
- set_menu_sensitivity("<Main>/File/Close", FALSE);
- set_menu_sensitivity("<Main>/File/Reload", FALSE);
- set_menu_sensitivity("<Main>/Tools/Summary", FALSE);
-#endif
}
void
file_save_cmd_cb(GtkWidget *w, gpointer data) {
file_sel = gtk_file_selection_new ("Ethereal: Save Capture File");
-
- /* Connect the ok_button to file_ok_sel_cb function and pass along the
- pointer to the filter entry */
+
+ /* Connect the ok_button to file_save_ok_cb function and pass along a
+ pointer to the file selection box widget */
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
"clicked", (GtkSignalFunc) file_save_ok_cb, file_sel );
void
file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
- file_sel = gtk_file_selection_new ("Ethereal: Save Capture File as");
+ file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
- /* Connect the ok_button to file_ok_sel_cb function and pass along the
- pointer to the filter entry */
+ /* Connect the ok_button to file_save_as_ok_cb function and pass along a
+ pointer to the file selection box widget */
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
"clicked", (GtkSignalFunc) file_save_as_ok_cb, file_sel );
if (!file_mv(cf.save_file, cf_name))
return;
+
g_free(cf.save_file);
cf.save_file = g_strdup(cf_name);
cf.user_saved = 1;
- err = load_cap_file(cf_name, &cf);
- if (err != 0) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- file_open_error_message(err, FALSE), cf_name);
+ if ((err = open_cap_file(cf_name, &cf)) == 0) {
+ err = read_cap_file(&cf);
+ set_menu_sensitivity("/File/Save", FALSE);
+ set_menu_sensitivity("/File/Save As...", TRUE);
}
-
-#ifdef USE_ITEM
- set_menu_sensitivity("/File/Save", FALSE);
- set_menu_sensitivity("/File/Save As...", TRUE);
-#else
- set_menu_sensitivity("<Main>/File/Save", FALSE);
- set_menu_sensitivity("<Main>/File/Save As...", TRUE);
-#endif
}
static void
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
gtk_widget_hide(GTK_WIDGET (fs));
gtk_widget_destroy(GTK_WIDGET (fs));
-
- if (!file_cp(cf.save_file, cf_name))
+ if (!file_cp(cf.filename, cf_name))
return;
- g_free(cf.save_file);
- cf.save_file = g_strdup(cf_name);
+ g_free(cf.filename);
+ cf.filename = g_strdup(cf_name);
cf.user_saved = 1;
- err = load_cap_file(cf_name, &cf);
- if (err != 0) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- file_open_error_message(err, FALSE), cf_name);
+ if ((err = open_cap_file(cf.filename, &cf)) == 0) {
+ err = read_cap_file(&cf);
+ set_menu_sensitivity("/File/Save", FALSE);
+ set_menu_sensitivity("/File/Save As...", TRUE);
}
-
-#ifdef USE_ITEM
- set_menu_sensitivity("/File/Save", FALSE);
- set_menu_sensitivity("/File/Save As...", TRUE);
-#else
- set_menu_sensitivity("<Main>/File/Save", FALSE);
- set_menu_sensitivity("<Main>/File/Save As...", TRUE);
-#endif
}
-/* Reload a file using the current display filter */
+/* Reload a file using the current read and display filters */
void
file_reload_cmd_cb(GtkWidget *w, gpointer data) {
/*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
GtkWidget *filter_te;
- int err;
filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
if (cf.dfilter) g_free(cf.dfilter);
cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
- err = load_cap_file(cf.filename, &cf);
- if (err != 0) {
- simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
- cf.filename);
+ if (open_cap_file(cf.filename, &cf) == 0)
+ read_cap_file(&cf);
+ /* XXX - change the menu if the open fails? */
+}
+
+/* Run the current display filter on the current packet set, and
+ redisplay. */
+static void
+filter_activate_cb(GtkWidget *w, gpointer data)
+{
+ char *s = gtk_entry_get_text(GTK_ENTRY(w));
+
+ if (cf.dfilter)
+ g_free(cf.dfilter);
+
+ /* simple check for empty string. XXX - need to modify to search for /^\s+$/ */
+ if (s[0] == '\0' ) {
+ cf.dfilter = NULL;
}
+ else {
+ cf.dfilter = g_strdup(s);
+ }
+
+ filter_packets(&cf);
+}
+
+/*
+ * Remember whether we printed to a printer or a file the last time we
+ * printed something.
+ */
+static int print_to_file;
+
+/* Keys for gtk_object_set_data */
+#define PRINT_CMD_LB_KEY "printer_command_label"
+#define PRINT_CMD_TE_KEY "printer_command_entry"
+#define PRINT_FILE_BT_KEY "printer_file_button"
+#define PRINT_FILE_TE_KEY "printer_file_entry"
+#define PRINT_DEST_RB_KEY "printer_destination_radio_button"
+
+/* Print the capture */
+void
+file_print_cmd_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *print_w;
+ GtkWidget *main_vb, *main_tb, *button;
+#if 0
+ GtkWidget *format_hb, *format_lb;
+ GSList *format_grp;
+#endif
+ GtkWidget *dest_rb;
+ GtkWidget *dest_hb, *dest_lb;
+ GtkWidget *cmd_lb, *cmd_te;
+ GtkWidget *file_bt_hb, *file_bt, *file_te;
+ GSList *dest_grp;
+ GtkWidget *bbox, *ok_bt, *cancel_bt;
+
+ /* XXX - don't pop up one if there's already one open; instead,
+ give it the input focus if that's possible. */
+
+ print_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(print_w), "Ethereal: Print");
+
+ /* Enclosing containers for each row of widgets */
+ main_vb = gtk_vbox_new(FALSE, 5);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ gtk_container_add(GTK_CONTAINER(print_w), main_vb);
+ gtk_widget_show(main_vb);
+
+ main_tb = gtk_table_new(4, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
+ gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
+ gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
+ gtk_widget_show(main_tb);
+
+ /* XXX - printing multiple frames in PostScript looks as if it's
+ tricky - you have to deal with page boundaries, I think -
+ and I'll have to spend some time learning enough about
+ PostScript to figure it out, so, for now, we only print
+ multiple frames as text. */
+#if 0
+ /* Output format */
+ format_lb = gtk_label_new("Format:");
+ gtk_misc_set_alignment(GTK_MISC(format_lb), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), format_lb, 0, 1, 0, 1);
+ gtk_widget_show(format_lb);
+
+ format_hb = gtk_hbox_new(FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), format_hb, 1, 2, 0, 1);
+ gtk_widget_show(format_hb);
+
+ button = gtk_radio_button_new_with_label(NULL, "Plain Text");
+ if (prefs.pr_format == PR_FMT_TEXT)
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
+ format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
+ gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
+ gtk_widget_show(button);
+
+ button = gtk_radio_button_new_with_label(format_grp, "PostScript");
+ if (prefs.pr_format == PR_FMT_PS)
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
+ gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
+ gtk_widget_show(button);
+#endif
+
+ /* Output destination */
+ dest_lb = gtk_label_new("Print to:");
+ gtk_misc_set_alignment(GTK_MISC(dest_lb), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_lb, 0, 1, 1, 2);
+ gtk_widget_show(dest_lb);
+
+ dest_hb = gtk_hbox_new(FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_hb, 1, 2, 1, 2);
+ gtk_widget_show(dest_hb);
+
+ button = gtk_radio_button_new_with_label(NULL, "Command");
+ if (!print_to_file)
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
+ dest_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
+ gtk_box_pack_start(GTK_BOX(dest_hb), button, FALSE, FALSE, 10);
+ gtk_widget_show(button);
+
+ dest_rb = gtk_radio_button_new_with_label(dest_grp, "File");
+ if (print_to_file)
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_rb), TRUE);
+ gtk_signal_connect(GTK_OBJECT(dest_rb), "toggled",
+ GTK_SIGNAL_FUNC(print_cmd_toggle_dest), NULL);
+ gtk_box_pack_start(GTK_BOX(dest_hb), dest_rb, FALSE, FALSE, 10);
+ gtk_widget_show(dest_rb);
+
+ /* Command text entry */
+ cmd_lb = gtk_label_new("Command:");
+ gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_LB_KEY, cmd_lb);
+ gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_lb, 0, 1, 2, 3);
+ gtk_widget_set_sensitive(cmd_lb, !print_to_file);
+ gtk_widget_show(cmd_lb);
+
+ cmd_te = gtk_entry_new();
+ gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_TE_KEY, cmd_te);
+ if (prefs.pr_cmd)
+ gtk_entry_set_text(GTK_ENTRY(cmd_te), prefs.pr_cmd);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_te, 1, 2, 2, 3);
+ gtk_widget_set_sensitive(cmd_te, !print_to_file);
+ gtk_widget_show(cmd_te);
+
+ /* File button and text entry */
+ file_bt_hb = gtk_hbox_new(FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), file_bt_hb, 0, 1, 3, 4);
+ gtk_widget_show(file_bt_hb);
+
+ file_bt = gtk_button_new_with_label("File:");
+ gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_BT_KEY, file_bt);
+ gtk_box_pack_end(GTK_BOX(file_bt_hb), file_bt, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(file_bt, print_to_file);
+ gtk_widget_show(file_bt);
+
+ file_te = gtk_entry_new();
+ gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_TE_KEY, file_te);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), file_te, 1, 2, 3, 4);
+ gtk_widget_set_sensitive(file_te, print_to_file);
+ gtk_widget_show(file_te);
+
+ gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
+ GTK_SIGNAL_FUNC(print_file_cb), GTK_OBJECT(file_te));
+
+ /* Button row: OK and Cancel buttons */
+ bbox = gtk_hbutton_box_new();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(main_vb), bbox);
+ gtk_widget_show(bbox);
+
+ ok_bt = gtk_button_new_with_label ("OK");
+ gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_DEST_RB_KEY, dest_rb);
+ gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
+ gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
+ gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
+ GTK_SIGNAL_FUNC(print_ok_cb), GTK_OBJECT(print_w));
+ GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
+ gtk_widget_grab_default(ok_bt);
+ gtk_widget_show(ok_bt);
+
+ cancel_bt = gtk_button_new_with_label ("Cancel");
+ gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
+ GTK_SIGNAL_FUNC(print_close_cb), GTK_OBJECT(print_w));
+ GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
+ gtk_widget_show(cancel_bt);
+
+#if 0
+ display_opt_window_active = TRUE;
+#endif
+ gtk_widget_show(print_w);
+}
+
+static void
+print_cmd_toggle_dest(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *cmd_lb, *cmd_te, *file_bt, *file_te;
+ int to_file;
+
+ cmd_lb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
+ PRINT_CMD_LB_KEY));
+ cmd_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
+ PRINT_CMD_TE_KEY));
+ file_bt = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
+ PRINT_FILE_BT_KEY));
+ file_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
+ PRINT_FILE_TE_KEY));
+ if (GTK_TOGGLE_BUTTON (widget)->active) {
+ /* They selected "Print to File" */
+ to_file = TRUE;
+ } else {
+ /* They selected "Print to Command" */
+ to_file = FALSE;
+ }
+ gtk_widget_set_sensitive(cmd_lb, !to_file);
+ gtk_widget_set_sensitive(cmd_te, !to_file);
+ gtk_widget_set_sensitive(file_bt, to_file);
+ gtk_widget_set_sensitive(file_te, to_file);
+}
+
+static void
+print_file_cb(GtkWidget *file_bt, gpointer file_te)
+{
+ GtkWidget *fs;
+
+ fs = gtk_file_selection_new ("Ethereal: Print to File");
+ gtk_object_set_data(GTK_OBJECT(fs), PRINT_FILE_TE_KEY, file_te);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked", (GtkSignalFunc) print_fs_ok_cb, fs);
+
+ /* Connect the cancel_button to destroy the widget */
+ gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
+ "clicked", (GtkSignalFunc) print_fs_cancel_cb, fs);
+
+ gtk_widget_show(fs);
+}
+
+static void
+print_fs_ok_cb(GtkWidget *w, gpointer data)
+{
+
+ gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
+ PRINT_FILE_TE_KEY)),
+ gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
+ gtk_widget_destroy(GTK_WIDGET(data));
+}
+
+static void
+print_fs_cancel_cb(GtkWidget *w, gpointer data)
+{
+ gtk_widget_destroy(GTK_WIDGET(data));
+}
+
+static void
+print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
+{
+ GtkWidget *button;
+ char *dest;
+
+ button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
+ PRINT_DEST_RB_KEY);
+ if (GTK_TOGGLE_BUTTON (button)->active)
+ print_to_file = TRUE;
+ else
+ print_to_file = FALSE;
+
+ if (print_to_file)
+ dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
+ PRINT_FILE_TE_KEY))));
+ else
+ dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
+ PRINT_CMD_TE_KEY))));
+
+ gtk_widget_destroy(GTK_WIDGET(parent_w));
+#if 0
+ display_opt_window_active = FALSE;
+#endif
+
+ /* Now print the packets */
+ if (!print_packets(&cf, print_to_file, dest)) {
+ if (print_to_file)
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ file_write_error_message(errno), dest);
+ else
+ simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
+ prefs.pr_cmd);
+ }
+
+ g_free(dest);
+}
+
+static void
+print_close_cb(GtkWidget *close_bt, gpointer parent_w)
+{
+
+ gtk_grab_remove(GTK_WIDGET(parent_w));
+ gtk_widget_destroy(GTK_WIDGET(parent_w));
+#if 0
+ display_opt_window_active = FALSE;
+#endif
}
/* Print a packet */
void
-file_print_cmd_cb(GtkWidget *widget, gpointer data) {
- print_tree(cf.pd, fd, GTK_TREE(tree_view));
+file_print_packet_cmd_cb(GtkWidget *widget, gpointer data) {
+ FILE *fh;
+
+ switch (prefs.pr_dest) {
+
+ case PR_DEST_CMD:
+ fh = popen(prefs.pr_cmd, "w");
+ break;
+
+ case PR_DEST_FILE:
+ fh = fopen(prefs.pr_file, "w");
+ break;
+
+ default:
+ fh = NULL; /* XXX - "can't happen" */
+ break;
+ }
+ if (fh == NULL) {
+ switch (prefs.pr_dest) {
+
+ case PR_DEST_CMD:
+ simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
+ prefs.pr_cmd);
+ break;
+
+ case PR_DEST_FILE:
+ simple_dialog(ESD_TYPE_WARN, NULL, file_write_error_message(errno),
+ prefs.pr_file);
+ break;
+ }
+ return;
+ }
+
+ print_preamble(fh);
+ proto_tree_print(-1, (GNode*) cf.protocol_tree, cf.pd, cf.fd, fh);
+ print_finale(fh);
+ close_print_dest(prefs.pr_dest == PR_DEST_FILE, fh);
}
/* What to do when a list item is selected/unselected */
void
packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
+#ifdef HAVE_LIBPCAP
if (!sync_mode) {
- if (cf.wth) return;
+#endif
+ if (cf.wth)
+ return;
+#ifdef HAVE_LIBPCAP
}
+#endif
blank_packetinfo();
- gtk_text_freeze(GTK_TEXT(byte_view));
- gtk_text_set_point(GTK_TEXT(byte_view), 0);
- gtk_text_forward_delete(GTK_TEXT(byte_view),
- gtk_text_get_length(GTK_TEXT(byte_view)));
-
- /* get the frame data struct pointer for this frame */
- fd = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(w), row);
- fseek(cf.fh, fd->file_off, SEEK_SET);
- fread(cf.pd, sizeof(guint8), fd->cap_len, cf.fh);
-
- /* create the logical protocol tree */
- if (protocol_tree)
- proto_tree_free(protocol_tree);
- protocol_tree = proto_tree_create_root();
- dissect_packet(cf.pd, fd, protocol_tree);
-
- /* display the GUI protocol tree and hex dump */
- proto_tree_draw(protocol_tree, tree_view);
- packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len, -1, -1);
- gtk_text_thaw(GTK_TEXT(byte_view));
+ select_packet(&cf, row);
}
void
packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
- gtk_text_freeze(GTK_TEXT(byte_view));
- gtk_text_set_point(GTK_TEXT(byte_view), 0);
- gtk_text_forward_delete(GTK_TEXT(byte_view),
- gtk_text_get_length(GTK_TEXT(byte_view)));
- gtk_text_thaw(GTK_TEXT(byte_view));
- gtk_tree_clear_items(GTK_TREE(tree_view), 0,
- g_list_length(GTK_TREE(tree_view)->children));
+ unselect_packet(&cf);
}
void
-tree_view_cb(GtkWidget *w) {
+tree_view_cb(GtkWidget *w, gpointer data) {
tree_selected_start = -1;
tree_selected_len = -1;
gtk_text_set_point(GTK_TEXT(byte_view), 0);
gtk_text_forward_delete(GTK_TEXT(byte_view),
gtk_text_get_length(GTK_TEXT(byte_view)));
- packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len,
+ packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.fd->cap_len,
tree_selected_start,
tree_selected_len);
}
void blank_packetinfo() {
- pi.srcip = 0;
- pi.destip = 0;
+ pi.ip_src = 0;
+ pi.ip_dst = 0;
pi.ipproto = 0;
pi.srcport = 0;
pi.destport = 0;
/* Things to do when the main window is realized */
void
main_realize_cb(GtkWidget *w, gpointer data) {
+#ifdef HAVE_LIBPCAP
if (start_capture) {
capture();
start_capture = 0;
}
+#endif
}
+#ifdef HAVE_LIBPCAP
static void
sigusr2_handler(int sig) {
sigusr2_received = 1;
signal(SIGUSR2, sigusr2_handler);
}
+#endif
/* call initialization routines at program startup time */
static void
dfilter_init();
}
+static void
+ethereal_proto_cleanup(void) {
+ proto_cleanup();
+ dfilter_cleanup();
+}
+
static void
print_usage(void) {
int
main(int argc, char *argv[])
{
- int opt, i;
+ char *command_name, *s;
+ int i;
+#ifndef WIN32
+ int opt;
extern char *optarg;
+#endif
char *pf_path;
int pf_open_errno = 0;
int err;
GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane,
*bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox,
*tv_scrollw, *filter_bt, *filter_te;
-#ifdef GTK_HAVE_FEATURES_1_1_0
- GtkAccelGroup *accel;
-#else
- GtkAcceleratorTable *accel;
-#endif
-
-#ifdef GTK_HAVE_FEATURES_1_1_4
- GtkWidget *packet_sw;
-#endif
+ GtkStyle *pl_style;
+ GtkAccelGroup *accel;
+ GtkWidget *packet_sw;
gint pl_size = 280, tv_size = 95, bv_size = 75;
- gchar *rc_file, *cf_name = NULL;
+ gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
+ dfilter *rfcode = NULL;
+ gboolean rfilter_parse_failed = FALSE;
e_prefs *prefs;
- gint *col_fmt;
+ gchar **col_title;
ethereal_path = argv[0];
+ /* If invoked as "ethereal-dump-fields", we dump out a glossary of
+ display filter symbols; we specify that by checking the name,
+ so that we can do so before looking at the argument list -
+ we don't want to look at the argument list, because we don't
+ want to call "gtk_init()", because we don't want to have to
+ do any X stuff just to do a build. */
+ command_name = strrchr(ethereal_path, '/');
+ if (command_name == NULL)
+ command_name = ethereal_path;
+ else
+ command_name++;
+ if (strcmp(command_name, "ethereal-dump-fields") == 0) {
+ ethereal_proto_init();
+ proto_registrar_dump();
+ exit(0);
+ }
+
/* Let GTK get its args */
gtk_init (&argc, &argv);
-
prefs = read_prefs(&pf_path);
if (pf_path != NULL) {
/* The preferences file exists, but couldn't be opened; "pf_path" is
failed. */
pf_open_errno = errno;
}
-
+
/* Initialize the capture file struct */
cf.plist = NULL;
+ cf.plist_end = NULL;
cf.wth = NULL;
cf.fh = NULL;
+ cf.rfcode = NULL;
cf.dfilter = NULL;
+ cf.dfcode = dfilter_new();
+#ifdef HAVE_LIBPCAP
cf.cfilter = NULL;
- cf.dfcode = NULL;
+#endif
cf.iface = NULL;
cf.save_file = NULL;
+ cf.save_file_fd = -1;
cf.user_saved = 0;
- cf.snap = MAX_PACKET_SIZE;
+ cf.snap = WTAP_MAX_PACKET_SIZE;
cf.count = 0;
cf.cinfo.num_cols = prefs->num_cols;
- cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
+ cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
/* Assemble the compile-time options */
snprintf(comp_info_str, 256,
#ifdef GTK_MAJOR_VERSION
- "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
- GTK_MICRO_VERSION
+ "GTK+ %d.%d.%d, %s libpcap", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
+ GTK_MICRO_VERSION,
+#else
+ "GTK+ (version unknown), %s libpcap",
+#endif
+
+#ifdef HAVE_LIBPCAP
+ "with"
#else
- "GTK+ (version unknown)"
+ "without"
#endif
);
+#ifndef WIN32
/* Now get our args */
- while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:Ss:t:T:w:v")) != EOF) {
+ while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
switch (opt) {
case 'b': /* Bold font */
bold_font = g_strdup(optarg);
case 'c': /* Capture xxx packets */
cf.count = atoi(optarg);
break;
+#ifdef HAVE_LIBPCAP
case 'f':
cf.cfilter = g_strdup(optarg);
break;
case 'F': /* Fork to capture */
fork_mode = 1;
break;
+#endif
case 'h': /* Print help and exit */
print_usage();
exit(0);
case 'n': /* No name resolution */
g_resolving_actif = 0;
break;
+#ifdef HAVE_LIBPCAP
case 'k': /* Start capture immediately */
start_capture = 1;
break;
+#endif
case 'P': /* Packet list pane height */
pl_size = atoi(optarg);
break;
+#ifdef HAVE_LIBPCAP
case 'Q': /* Quit after capture (just capture to file) */
quit_after_cap = 1;
start_capture = 1; /*** -Q implies -k !! ***/
break;
+#endif
case 'r': /* Read capture file xxx */
cf_name = g_strdup(optarg);
break;
+ case 'R': /* Read file filter */
+ rfilter = optarg;
+ break;
+#ifdef HAVE_LIBPCAP
case 's': /* Set the snapshot (capture) length */
cf.snap = atoi(optarg);
break;
sync_mode = 1;
fork_mode = 1; /* -S implies -F */
break;
+#endif
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
timestamp_type = RELATIVE;
printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
exit(0);
break;
- case 'w': /* Write capture file xxx */
+#ifdef HAVE_LIBPCAP
+ case 'w': /* Write to capture file xxx */
cf.save_file = g_strdup(optarg);
break;
+ case 'W': /* Write to capture file FD xxx */
+ cf.save_file_fd = atoi(optarg);
+ break;
+#endif
}
}
+#endif
if (start_capture) {
if (cf.iface == NULL) {
fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-w\" flag\n");
exit(1);
}
+#ifdef HAVE_LIBPCAP
+ if (fork_mode) {
+ if (cf.save_file_fd == -1) {
+ fprintf(stderr, "ethereal: \"-k\" flag was specified with \"-%c\" flag but without \"-W\" flag\n",
+ (sync_mode ? 'S' : 'F'));
+ exit(1);
+ }
+ }
+#endif
}
+#ifdef HAVE_LIBPCAP
if (sync_mode)
signal(SIGUSR2, sigusr2_handler);
+#endif
/* Build the column format array */
- col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
+ col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
for (i = 0; i < cf.cinfo.num_cols; i++) {
- col_fmt[i] = get_column_format(i);
- cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
+ cf.cinfo.col_fmt[i] = get_column_format(i);
+ col_title[i] = g_strdup(get_column_title(i));
cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
NUM_COL_FMTS);
- get_column_format_matches(cf.cinfo.fmt_matx[i], col_fmt[i]);
+ get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
- cf.cinfo.col_width[i] = 0;
}
if (cf.snap < 1)
- cf.snap = MAX_PACKET_SIZE;
+ cf.snap = WTAP_MAX_PACKET_SIZE;
else if (cf.snap < MIN_PACKET_SIZE)
cf.snap = MIN_PACKET_SIZE;
/* Menu bar */
get_main_menu(&menubar, &accel);
-#ifdef GTK_HAVE_FEATURES_1_1_0
gtk_window_add_accel_group(GTK_WINDOW(window), accel);
-#else
- gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
-#endif
gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
gtk_widget_show(menubar);
gtk_widget_show(l_pane);
/* Packet list */
- packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols,
- cf.cinfo.col_title);
+ packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols, col_title);
gtk_clist_column_titles_passive(GTK_CLIST(packet_list));
-#ifdef GTK_HAVE_FEATURES_1_1_4
packet_sw = gtk_scrolled_window_new(NULL, NULL);
gtk_widget_show(packet_sw);
gtk_container_add(GTK_CONTAINER(packet_sw), packet_list);
-#endif
pl_style = gtk_style_new();
gdk_font_unref(pl_style->font);
pl_style->font = m_r_font;
gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
for (i = 0; i < cf.cinfo.num_cols; i++) {
- gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
- gdk_string_width(pl_style->font, cf.cinfo.col_title[i]));
- if (col_fmt[i] == COL_NUMBER)
+ if (get_column_resize_type(cf.cinfo.col_fmt[i]) != RESIZE_MANUAL)
+ gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
+
+ /* Right-justify the packet number column. */
+ if (cf.cinfo.col_fmt[i] == COL_NUMBER)
gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
GTK_JUSTIFY_RIGHT);
+
+ /* Save static column sizes to use during a "-S" capture, so that
+ the columns don't resize during a live capture. */
+ cf.cinfo.col_width[i] = get_column_width(get_column_format(i),
+ pl_style->font);
}
gtk_widget_set_usize(packet_list, -1, pl_size);
-#ifdef GTK_HAVE_FEATURES_1_1_4
gtk_paned_add1(GTK_PANED(u_pane), packet_sw);
-#else
- gtk_paned_add1(GTK_PANED(u_pane), packet_list);
-#endif
gtk_widget_show(packet_list);
/* Tree view */
gtk_widget_show(tv_scrollw);
tree_view = gtk_tree_new();
-#ifdef GTK_HAVE_FEATURES_1_1_4
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tv_scrollw),
tree_view);
-#else
- gtk_container_add(GTK_CONTAINER(tv_scrollw), tree_view);
-#endif
gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
+
+ /* XXX - what's the difference between the next two lines? */
gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
- gtk_tree_set_view_mode(GTK_TREE(tree_view), TRUE);
+ gtk_tree_set_view_mode(GTK_TREE(tree_view), GTK_TREE_VIEW_ITEM);
+
gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
GTK_SIGNAL_FUNC(tree_view_cb), NULL);
gtk_widget_show(tree_view);
filter_te = gtk_entry_new();
gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_te, TRUE, TRUE, 3);
+ gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
+ GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
gtk_widget_show(filter_te);
-#ifdef USE_ITEM
+ /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
+ * of any widget that ends up calling a callback which needs
+ * that text entry pointer */
set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
+ set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY,
filter_te);
-#else
- set_menu_object_data("<Main>/File/Open...", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("<Main>/File/Reload", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("<Main>/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
- filter_te);
-#endif
+
info_bar = gtk_statusbar_new();
main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
gtk_widget_show(window);
+ colors_init(&cf);
+
/* If we were given the name of a capture file, read it in now;
we defer it until now, so that, if we can't open it, and pop
- up an alert box, the alert box is more likely to cmoe up on
+ up an alert box, the alert box is more likely to come up on
top of the main window - but before the preference-file-error
alert box, so, if we get one of those, it's more likely to come
up on top of us. */
if (cf_name) {
- err = load_cap_file(cf_name, &cf);
- if (err != 0) {
- simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
- cf_name);
+ if (rfilter != NULL) {
+ rfcode = dfilter_new();
+ if (dfilter_compile(rfcode, rfilter) != 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+ dfilter_destroy(rfcode);
+ rfilter_parse_failed = TRUE;
+ }
+ }
+ if (!rfilter_parse_failed) {
+ if ((err = open_cap_file(cf_name, &cf)) == 0) {
+ cf.rfcode = rfcode;
+ err = read_cap_file(&cf);
+ s = strrchr(cf_name, '/');
+ if (s) {
+ last_open_dir = cf_name;
+ *s = '\0';
+ }
+ set_menu_sensitivity("/File/Save As...", TRUE);
+ }
}
- cf_name[0] = '\0';
-#ifdef USE_ITEM
- set_menu_sensitivity("/File/Save As...", TRUE);
- set_menu_sensitivity("/Tools/Summary", TRUE);
-#else
- set_menu_sensitivity("<Main>/File/Save As...", TRUE);
- set_menu_sensitivity("<Main>/Tools/Summary", TRUE);
-#endif
}
/* If we failed to open the preferences file, pop up an alert box;
come up on top of the main window. */
if (pf_path != NULL) {
simple_dialog(ESD_TYPE_WARN, NULL,
- "Can't open preferences file\n\"%s\": %s.", pf_path,
+ "Could not open preferences file\n\"%s\": %s.", pf_path,
strerror(pf_open_errno));
}
gtk_main();
+ ethereal_proto_cleanup();
+
exit(0);
}