3 * $Id: ethereal.c,v 1.98 1999/08/20 19:43:10 gram Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 * - Live browser/capture display
31 * - Check for end of packet in dissect_* routines.
33 * - Multiple window support
34 * - Add cut/copy/paste
35 * - Create header parsing routines
36 * - Check fopens, freads, fwrites
37 * - Make byte view scrollbars automatic?
38 * - Make byte view selections more fancy?
57 #include <sys/types.h>
65 #ifdef HAVE_NETINET_IN_H
66 #include <netinet/in.h>
71 #ifdef NEED_SNPRINTF_H
77 # include "snprintf.h"
80 #ifdef NEED_STRERROR_H
85 #include "timestamp.h"
98 #include "gtkpacket.h"
101 static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
102 static void file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs);
103 static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
104 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
105 static void print_file_cb(GtkWidget *file_bt, gpointer file_te);
106 static void print_fs_ok_cb(GtkWidget *w, gpointer data);
107 static void print_fs_cancel_cb(GtkWidget *w, gpointer data);
108 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
109 static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
111 FILE *data_out_file = NULL;
114 GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
116 GdkFont *m_r_font, *m_b_font;
117 guint main_ctx, file_ctx;
118 gint start_capture = 0;
119 gchar comp_info_str[256];
120 gchar *ethereal_path = NULL;
121 gchar *medium_font = MONO_MEDIUM_FONT;
122 gchar *bold_font = MONO_BOLD_FONT;
123 gchar *last_open_dir = NULL;
125 ts_type timestamp_type = RELATIVE;
127 GtkStyle *item_style;
130 int sync_mode; /* allow sync */
131 int sync_pipe[2]; /* used to sync father */
132 int fork_mode; /* fork a child to do the capture */
133 int sigusr2_received = 0;
134 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
137 /* Specifies byte offsets for object selected in tree */
138 static gint tree_selected_start=-1, tree_selected_len=-1;
140 #define E_DFILTER_TE_KEY "display_filter_te"
141 #define E_RFILTER_TE_KEY "read_filter_te"
143 /* About Ethereal window */
145 about_ethereal( GtkWidget *w, gpointer data ) {
146 simple_dialog(ESD_TYPE_INFO, NULL,
147 "GNU Ethereal - network protocol analyzer\n"
148 "Version %s (C) 1998 Gerald Combs <gerald@zing.org>\n"
149 "Compiled with %s\n\n"
152 "Gilbert Ramirez <gramirez@tivoli.com>\n"
153 "Hannes R. Boehm <hannes@boehm.org>\n"
154 "Mike Hall <mlh@io.com>\n"
155 "Bobo Rajec <bobo@bsp-consulting.sk>\n"
156 "Laurent Deniel <deniel@worldnet.fr>\n"
157 "Don Lafontaine <lafont02@cn.ca>\n"
158 "Guy Harris <guy@netapp.com>\n"
159 "Simon Wilkinson <sxw@dcs.ed.ac.uk>\n"
160 "Joerg Mayer <jmayer@telemation.de>\n"
161 "Martin Maciaszek <fastjack@i-s-o.net>\n"
162 "Didier Jorand <Didier.Jorand@alcatel.fr>\n"
163 "Jun-ichiro itojun Hagino <itojun@iijlab.net>\n"
164 "Richard Sharpe <sharpe@ns.aus.com>\n"
165 "John McDermott <jjm@jkintl.com>\n"
166 "Jeff Jahr <jjahr@shastanets.com>\n"
167 "Brad Robel-Forrest <bradr@watchguard.com>\n"
168 "Ashok Narayanan <ashokn@cisco.com>\n"
169 "Aaron Hillegass <aaron@classmax.com>\n"
170 "Jason Lango <jal@netapp.com>\n"
171 "Johan Feyaerts <Johan.Feyaerts@siemens.atea.be>\n"
172 "Olivier Abad <abad@daba.dhis.org>\n"
173 "Thierry Andry <Thierry.Andry@advalvas.be>\n"
174 "Jeff Foster <jjfoste@woodward.com>\n"
176 "\nSee http://ethereal.zing.org for more information",
177 VERSION, comp_info_str);
180 /* Update the progress bar */
182 file_progress_cb(gpointer p) {
183 capture_file *cf = (capture_file*) p;
184 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
185 (gfloat) ftell(cf->fh) / (gfloat) cf->f_len);
189 /* Follow the TCP stream, if any, to which the last packet that we called
190 a dissection routine on belongs (this might be the most recently
191 selected packet, or it might be the last packet in the file). */
193 follow_stream_cb( GtkWidget *w, gpointer data ) {
194 char filename1[128+1];
195 GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
199 if( pi.ipproto == 6 ) {
200 /* we got tcp so we can follow */
201 /* Create a temporary file into which to dump the reassembled data
202 from the TCP stream, and set "data_out_file" to refer to it, so
203 that the TCP code will write to it.
205 XXX - it might be nicer to just have the TCP code directly
206 append stuff to the text widget for the TCP stream window,
207 if we can arrange that said window not pop up until we're
209 tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
211 simple_dialog(ESD_TYPE_WARN, NULL,
212 "Could not create temporary file %s: %s", filename1, strerror(errno));
215 data_out_file = fdopen( tmp_fd, "w" );
216 if( data_out_file == NULL ) {
217 simple_dialog(ESD_TYPE_WARN, NULL,
218 "Could not create temporary file %s: %s", filename1, strerror(errno));
224 /* Save any display filter we currently have. */
225 old_dfilter = cf.dfilter;
227 /* Create a new filter that matches all packets in the TCP stream,
228 and set the display filter entry accordingly */
229 reset_tcp_reassembly();
230 cf.dfilter = build_follow_filter( &pi );
232 /* Run the display filter so it goes in effect. */
235 /* the data_out_file should now be full of the streams information */
236 fclose( data_out_file );
238 /* the filename1 file now has all the text that was in the session */
239 streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
240 gtk_widget_set_name( streamwindow, "TCP stream window" );
241 gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
242 NULL, "WM destroy" );
243 gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
244 NULL, "WM destroy" );
245 if( incomplete_tcp_stream ) {
246 gtk_window_set_title( GTK_WINDOW(streamwindow),
247 "Contents of TCP stream (incomplete)" );
249 gtk_window_set_title( GTK_WINDOW(streamwindow),
250 "Contents of TCP stream" );
252 gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
253 gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
255 /* setup the container */
256 box = gtk_vbox_new( FALSE, 0 );
257 gtk_container_add( GTK_CONTAINER(streamwindow), box );
258 gtk_widget_show( box );
260 /* set up the table we attach to */
261 table = gtk_table_new( 1, 2, FALSE );
262 gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
263 gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
264 gtk_widget_show( table );
266 /* create a text box */
267 text = gtk_text_new( NULL, NULL );
268 gtk_text_set_editable( GTK_TEXT(text), FALSE);
269 gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
270 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
271 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
272 gtk_widget_show(text);
274 /* create the scrollbar */
275 vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
276 gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
277 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
278 gtk_widget_show( vscrollbar );
279 gtk_widget_realize( text );
281 /* stop the updates while we fill the text box */
282 gtk_text_freeze( GTK_TEXT(text) );
283 data_out_file = fopen( filename1, "r" );
284 if( data_out_file ) {
288 nchars = fread( buffer, 1, 1024, data_out_file );
289 gtk_text_insert( GTK_TEXT(text), m_r_font, NULL, NULL, buffer, nchars );
290 if( nchars < 1024 ) {
294 if( ferror( data_out_file ) ) {
295 simple_dialog(ESD_TYPE_WARN, NULL,
296 "Error reading temporary file %s: %s", filename1, strerror(errno));
298 fclose( data_out_file );
300 simple_dialog(ESD_TYPE_WARN, NULL,
301 "Could not open temporary file %s: %s", filename1, strerror(errno));
303 gtk_text_thaw( GTK_TEXT(text) );
305 data_out_file = NULL;
306 gtk_widget_show( streamwindow );
307 if( cf.dfilter != NULL ) {
308 g_free( cf.dfilter );
310 cf.dfilter = old_dfilter;
313 simple_dialog(ESD_TYPE_WARN, NULL,
314 "Error following stream. Please make\n"
315 "sure you have a TCP packet selected.");
319 /* Match selected byte pattern */
321 match_selected_cb(GtkWidget *w, gpointer data)
323 char *buf = g_malloc(1024);
324 GtkWidget *filter_te = NULL;
329 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
331 if (tree_selected_start<0) {
332 simple_dialog(ESD_TYPE_WARN, NULL,
333 "Error determining selected bytes. Please make\n"
334 "sure you have selected a field within the tree\n"
335 "view to be matched.");
339 c = cf.pd + tree_selected_start;
342 sprintf(ptr, "frame[%d : %d] == ", tree_selected_start, tree_selected_len);
343 ptr = buf+strlen(buf);
345 if (tree_selected_len == 1) {
346 sprintf(ptr, "0x%02x", *c++);
349 for (i=0;i<tree_selected_len; i++) {
351 sprintf(ptr, "%02x", *c++);
354 sprintf(ptr, ":%02x", *c++);
356 ptr = buf+strlen(buf);
360 if( cf.dfilter != NULL ) {
361 /* get rid of this one */
362 g_free( cf.dfilter );
364 /* create a new one and set the display filter entry accordingly */
367 gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
368 printf("set text to %s\n", cf.dfilter);
370 /* Run the display filter so it goes in effect. */
376 file_open_cmd_cb(GtkWidget *w, gpointer data) {
377 GtkWidget *filter_hbox, *filter_bt, *filter_te;
380 chdir(last_open_dir);
382 file_sel = gtk_file_selection_new ("Ethereal: Open Capture File");
384 /* Connect the ok_button to file_open_ok_cb function and pass along a
385 pointer to the file selection box widget */
386 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
387 "clicked", (GtkSignalFunc) file_open_ok_cb, file_sel );
389 gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
390 E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
392 filter_hbox = gtk_hbox_new(FALSE, 1);
393 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
394 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_sel)->action_area),
395 filter_hbox, FALSE, FALSE, 0);
396 gtk_widget_show(filter_hbox);
398 filter_bt = gtk_button_new_with_label("Filter:");
399 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
400 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
401 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
402 gtk_widget_show(filter_bt);
404 filter_te = gtk_entry_new();
405 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
406 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
407 gtk_widget_show(filter_te);
409 gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
410 E_RFILTER_TE_KEY, filter_te);
412 /* Connect the cancel_button to destroy the widget */
413 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
414 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
415 gtk_widget_destroy, GTK_OBJECT (file_sel));
418 if( fork_mode && (cf.save_file != NULL) )
420 if( cf.save_file != NULL )
422 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), cf.save_file);
424 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
426 gtk_widget_show(file_sel);
430 file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
431 gchar *cf_name, *rfilter, *s;
432 GtkWidget *filter_te;
433 dfilter *rfcode = NULL;
436 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
437 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_RFILTER_TE_KEY);
438 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
439 if (rfilter[0] != '\0') {
440 rfcode = dfilter_new();
441 if (dfilter_compile(rfcode, rfilter) != 0) {
442 simple_dialog(ESD_TYPE_WARN, NULL,
443 "Unable to parse filter string \"%s\".", rfilter);
444 dfilter_destroy(rfcode);
449 /* Try to open the capture file. */
450 if ((err = open_cap_file(cf_name, &cf)) != 0) {
451 /* We couldn't open it; don't dismiss the open dialog box,
452 just leave it around so that the user can, after they
453 dismiss the alert box popped up for the open error,
456 dfilter_destroy(rfcode);
460 /* Attach the new read filter to "cf" ("open_cap_file()" succeeded, so
461 it closed the previous capture file, and thus destroyed any
462 previous read filter attached to "cf"). */
465 /* We've crossed the Rubicon; get rid of the file selection box. */
466 gtk_widget_hide(GTK_WIDGET (fs));
467 gtk_widget_destroy(GTK_WIDGET (fs));
469 err = read_cap_file(&cf);
470 /* Save the directory name; we can write over cf_name. */
471 s = strrchr(cf_name, '/');
472 if (s && last_open_dir) {
474 if (strcmp(last_open_dir, cf_name) != 0) {
475 g_free(last_open_dir);
476 last_open_dir = g_strdup(cf_name);
479 else if (s) { /* ! last_open_dir */
481 last_open_dir = g_strdup(cf_name);
484 last_open_dir = NULL;
486 set_menu_sensitivity("/File/Save", FALSE);
487 set_menu_sensitivity("/File/Save As...", TRUE);
493 file_close_cmd_cb(GtkWidget *widget, gpointer data) {
494 close_cap_file(&cf, info_bar, file_ctx);
498 file_save_cmd_cb(GtkWidget *w, gpointer data) {
499 file_sel = gtk_file_selection_new ("Ethereal: Save Capture File");
501 /* Connect the ok_button to file_save_ok_cb function and pass along a
502 pointer to the file selection box widget */
503 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
504 "clicked", (GtkSignalFunc) file_save_ok_cb, file_sel );
506 /* Connect the cancel_button to destroy the widget */
507 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
508 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
509 gtk_widget_destroy, GTK_OBJECT (file_sel));
511 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
513 gtk_widget_show(file_sel);
517 file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
518 file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
520 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
521 pointer to the file selection box widget */
522 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
523 "clicked", (GtkSignalFunc) file_save_as_ok_cb, file_sel );
525 /* Connect the cancel_button to destroy the widget */
526 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
527 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
528 gtk_widget_destroy, GTK_OBJECT (file_sel));
530 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
531 gtk_widget_show(file_sel);
535 file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
539 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
540 gtk_widget_hide(GTK_WIDGET (fs));
541 gtk_widget_destroy(GTK_WIDGET (fs));
543 if (!file_mv(cf.save_file, cf_name))
546 g_free(cf.save_file);
547 cf.save_file = g_strdup(cf_name);
549 if ((err = open_cap_file(cf_name, &cf)) == 0) {
550 err = read_cap_file(&cf);
551 set_menu_sensitivity("/File/Save", FALSE);
552 set_menu_sensitivity("/File/Save As...", TRUE);
557 file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
561 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
562 gtk_widget_hide(GTK_WIDGET (fs));
563 gtk_widget_destroy(GTK_WIDGET (fs));
564 if (!file_cp(cf.filename, cf_name))
567 cf.filename = g_strdup(cf_name);
569 if ((err = open_cap_file(cf.filename, &cf)) == 0) {
570 err = read_cap_file(&cf);
571 set_menu_sensitivity("/File/Save", FALSE);
572 set_menu_sensitivity("/File/Save As...", TRUE);
576 /* Reload a file using the current read and display filters */
578 file_reload_cmd_cb(GtkWidget *w, gpointer data) {
579 /*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
580 GtkWidget *filter_te;
582 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
584 if (cf.dfilter) g_free(cf.dfilter);
585 cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
586 if (open_cap_file(cf.filename, &cf) == 0)
588 /* XXX - change the menu if the open fails? */
591 /* Run the current display filter on the current packet set, and
594 filter_activate_cb(GtkWidget *w, gpointer data)
596 char *s = gtk_entry_get_text(GTK_ENTRY(w));
601 /* simple check for empty string. XXX - need to modify to search for /^\s+$/ */
606 cf.dfilter = g_strdup(s);
613 * Remember whether we printed to a printer or a file the last time we
616 static int print_to_file;
618 /* Keys for gtk_object_set_data */
619 #define PRINT_CMD_LB_KEY "printer_command_label"
620 #define PRINT_CMD_TE_KEY "printer_command_entry"
621 #define PRINT_FILE_BT_KEY "printer_file_button"
622 #define PRINT_FILE_TE_KEY "printer_file_entry"
623 #define PRINT_DEST_RB_KEY "printer_destination_radio_button"
625 /* Print the capture */
627 file_print_cmd_cb(GtkWidget *widget, gpointer data)
630 GtkWidget *main_vb, *main_tb, *button;
632 GtkWidget *format_hb, *format_lb;
636 GtkWidget *dest_hb, *dest_lb;
637 GtkWidget *cmd_lb, *cmd_te;
638 GtkWidget *file_bt_hb, *file_bt, *file_te;
640 GtkWidget *bbox, *ok_bt, *cancel_bt;
642 /* XXX - don't pop up one if there's already one open; instead,
643 give it the input focus if that's possible. */
645 print_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
646 gtk_window_set_title(GTK_WINDOW(print_w), "Ethereal: Print");
648 /* Enclosing containers for each row of widgets */
649 main_vb = gtk_vbox_new(FALSE, 5);
650 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
651 gtk_container_add(GTK_CONTAINER(print_w), main_vb);
652 gtk_widget_show(main_vb);
654 main_tb = gtk_table_new(4, 2, FALSE);
655 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
656 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
657 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
658 gtk_widget_show(main_tb);
660 /* XXX - printing multiple frames in PostScript looks as if it's
661 tricky - you have to deal with page boundaries, I think -
662 and I'll have to spend some time learning enough about
663 PostScript to figure it out, so, for now, we only print
664 multiple frames as text. */
667 format_lb = gtk_label_new("Format:");
668 gtk_misc_set_alignment(GTK_MISC(format_lb), 1.0, 0.5);
669 gtk_table_attach_defaults(GTK_TABLE(main_tb), format_lb, 0, 1, 0, 1);
670 gtk_widget_show(format_lb);
672 format_hb = gtk_hbox_new(FALSE, 0);
673 gtk_table_attach_defaults(GTK_TABLE(main_tb), format_hb, 1, 2, 0, 1);
674 gtk_widget_show(format_hb);
676 button = gtk_radio_button_new_with_label(NULL, "Plain Text");
677 if (prefs.pr_format == PR_FMT_TEXT)
678 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
679 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
680 gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
681 gtk_widget_show(button);
683 button = gtk_radio_button_new_with_label(format_grp, "PostScript");
684 if (prefs.pr_format == PR_FMT_PS)
685 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
686 gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
687 gtk_widget_show(button);
690 /* Output destination */
691 dest_lb = gtk_label_new("Print to:");
692 gtk_misc_set_alignment(GTK_MISC(dest_lb), 1.0, 0.5);
693 gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_lb, 0, 1, 1, 2);
694 gtk_widget_show(dest_lb);
696 dest_hb = gtk_hbox_new(FALSE, 0);
697 gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_hb, 1, 2, 1, 2);
698 gtk_widget_show(dest_hb);
700 button = gtk_radio_button_new_with_label(NULL, "Command");
702 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
703 dest_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
704 gtk_box_pack_start(GTK_BOX(dest_hb), button, FALSE, FALSE, 10);
705 gtk_widget_show(button);
707 dest_rb = gtk_radio_button_new_with_label(dest_grp, "File");
709 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_rb), TRUE);
710 gtk_signal_connect(GTK_OBJECT(dest_rb), "toggled",
711 GTK_SIGNAL_FUNC(print_cmd_toggle_dest), NULL);
712 gtk_box_pack_start(GTK_BOX(dest_hb), dest_rb, FALSE, FALSE, 10);
713 gtk_widget_show(dest_rb);
715 /* Command text entry */
716 cmd_lb = gtk_label_new("Command:");
717 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_LB_KEY, cmd_lb);
718 gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
719 gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_lb, 0, 1, 2, 3);
720 gtk_widget_set_sensitive(cmd_lb, !print_to_file);
721 gtk_widget_show(cmd_lb);
723 cmd_te = gtk_entry_new();
724 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_TE_KEY, cmd_te);
726 gtk_entry_set_text(GTK_ENTRY(cmd_te), prefs.pr_cmd);
727 gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_te, 1, 2, 2, 3);
728 gtk_widget_set_sensitive(cmd_te, !print_to_file);
729 gtk_widget_show(cmd_te);
731 /* File button and text entry */
732 file_bt_hb = gtk_hbox_new(FALSE, 0);
733 gtk_table_attach_defaults(GTK_TABLE(main_tb), file_bt_hb, 0, 1, 3, 4);
734 gtk_widget_show(file_bt_hb);
736 file_bt = gtk_button_new_with_label("File:");
737 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_BT_KEY, file_bt);
738 gtk_box_pack_end(GTK_BOX(file_bt_hb), file_bt, FALSE, FALSE, 0);
739 gtk_widget_set_sensitive(file_bt, print_to_file);
740 gtk_widget_show(file_bt);
742 file_te = gtk_entry_new();
743 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_TE_KEY, file_te);
744 gtk_table_attach_defaults(GTK_TABLE(main_tb), file_te, 1, 2, 3, 4);
745 gtk_widget_set_sensitive(file_te, print_to_file);
746 gtk_widget_show(file_te);
748 gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
749 GTK_SIGNAL_FUNC(print_file_cb), GTK_OBJECT(file_te));
751 /* Button row: OK and Cancel buttons */
752 bbox = gtk_hbutton_box_new();
753 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
754 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
755 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
756 gtk_widget_show(bbox);
758 ok_bt = gtk_button_new_with_label ("OK");
759 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_DEST_RB_KEY, dest_rb);
760 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
761 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
762 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
763 GTK_SIGNAL_FUNC(print_ok_cb), GTK_OBJECT(print_w));
764 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
765 gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
766 gtk_widget_grab_default(ok_bt);
767 gtk_widget_show(ok_bt);
769 cancel_bt = gtk_button_new_with_label ("Cancel");
770 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
771 GTK_SIGNAL_FUNC(print_close_cb), GTK_OBJECT(print_w));
772 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
773 gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
774 gtk_widget_show(cancel_bt);
777 display_opt_window_active = TRUE;
779 gtk_widget_show(print_w);
783 print_cmd_toggle_dest(GtkWidget *widget, gpointer data)
785 GtkWidget *cmd_lb, *cmd_te, *file_bt, *file_te;
788 cmd_lb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
790 cmd_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
792 file_bt = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
794 file_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
796 if (GTK_TOGGLE_BUTTON (widget)->active) {
797 /* They selected "Print to File" */
800 /* They selected "Print to Command" */
803 gtk_widget_set_sensitive(cmd_lb, !to_file);
804 gtk_widget_set_sensitive(cmd_te, !to_file);
805 gtk_widget_set_sensitive(file_bt, to_file);
806 gtk_widget_set_sensitive(file_te, to_file);
810 print_file_cb(GtkWidget *file_bt, gpointer file_te)
814 fs = gtk_file_selection_new ("Ethereal: Print to File");
815 gtk_object_set_data(GTK_OBJECT(fs), PRINT_FILE_TE_KEY, file_te);
817 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
818 "clicked", (GtkSignalFunc) print_fs_ok_cb, fs);
820 /* Connect the cancel_button to destroy the widget */
821 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
822 "clicked", (GtkSignalFunc) print_fs_cancel_cb, fs);
828 print_fs_ok_cb(GtkWidget *w, gpointer data)
831 gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
833 gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
834 gtk_widget_destroy(GTK_WIDGET(data));
838 print_fs_cancel_cb(GtkWidget *w, gpointer data)
840 gtk_widget_destroy(GTK_WIDGET(data));
844 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
849 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
851 if (GTK_TOGGLE_BUTTON (button)->active)
852 print_to_file = TRUE;
854 print_to_file = FALSE;
857 dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
858 PRINT_FILE_TE_KEY))));
860 dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
861 PRINT_CMD_TE_KEY))));
863 gtk_widget_destroy(GTK_WIDGET(parent_w));
865 display_opt_window_active = FALSE;
868 /* Now print the packets */
869 if (!print_packets(&cf, print_to_file, dest)) {
871 simple_dialog(ESD_TYPE_WARN, NULL,
872 file_write_error_message(errno), dest);
874 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
882 print_close_cb(GtkWidget *close_bt, gpointer parent_w)
885 gtk_grab_remove(GTK_WIDGET(parent_w));
886 gtk_widget_destroy(GTK_WIDGET(parent_w));
888 display_opt_window_active = FALSE;
894 file_print_packet_cmd_cb(GtkWidget *widget, gpointer data) {
897 switch (prefs.pr_dest) {
900 fh = popen(prefs.pr_cmd, "w");
904 fh = fopen(prefs.pr_file, "w");
908 fh = NULL; /* XXX - "can't happen" */
912 switch (prefs.pr_dest) {
915 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
920 simple_dialog(ESD_TYPE_WARN, NULL, file_write_error_message(errno),
928 proto_tree_print(-1, (GNode*) cf.protocol_tree, cf.pd, cf.fd, fh);
930 close_print_dest(prefs.pr_dest == PR_DEST_FILE, fh);
933 /* What to do when a list item is selected/unselected */
935 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
946 select_packet(&cf, row);
950 packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
951 unselect_packet(&cf);
955 tree_view_cb(GtkWidget *w, gpointer data) {
957 tree_selected_start = -1;
958 tree_selected_len = -1;
960 if (GTK_TREE(w)->selection) {
961 tree_selected_start =
962 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
963 E_TREEINFO_START_KEY);
965 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
969 gtk_text_freeze(GTK_TEXT(byte_view));
970 gtk_text_set_point(GTK_TEXT(byte_view), 0);
971 gtk_text_forward_delete(GTK_TEXT(byte_view),
972 gtk_text_get_length(GTK_TEXT(byte_view)));
973 packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.fd->cap_len,
977 gtk_text_thaw(GTK_TEXT(byte_view));
981 file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
982 if (cf.save_file && !cf.user_saved) {
983 unlink(cf.save_file);
988 void blank_packetinfo() {
996 /* Things to do when the main window is realized */
998 main_realize_cb(GtkWidget *w, gpointer data) {
1000 if (start_capture) {
1009 sigusr2_handler(int sig) {
1010 sigusr2_received = 1;
1011 signal(SIGUSR2, sigusr2_handler);
1015 /* call initialization routines at program startup time */
1017 ethereal_proto_init(void) {
1026 fprintf(stderr, "This is GNU %s %s, compiled with %s\n", PACKAGE,
1027 VERSION, comp_info_str);
1028 fprintf(stderr, "%s [-vh] [-FkQS] [-b bold font] [-B byte view height] [-c count]\n",
1030 fprintf(stderr, " [-f \"filter expression\"] [-i interface] [-m medium font] [-n]\n");
1031 fprintf(stderr, " [-P packet list height] [-r infile] [-s snaplen]\n");
1032 fprintf(stderr, " [-t <time stamp format>] [-T tree view height] [-w savefile] \n");
1035 /* And now our feature presentation... [ fade to music ] */
1037 main(int argc, char *argv[])
1039 char *command_name, *s;
1043 extern char *optarg;
1046 int pf_open_errno = 0;
1048 GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane,
1049 *bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox,
1050 *tv_scrollw, *filter_bt, *filter_te;
1052 GtkAccelGroup *accel;
1053 GtkWidget *packet_sw;
1054 gint pl_size = 280, tv_size = 95, bv_size = 75;
1055 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1056 dfilter *rfcode = NULL;
1057 gboolean rfilter_parse_failed = FALSE;
1061 ethereal_path = argv[0];
1063 /* If invoked as "ethereal-dump-fields", we dump out a glossary of
1064 display filter symbols; we specify that by checking the name,
1065 so that we can do so before looking at the argument list -
1066 we don't want to look at the argument list, because we don't
1067 want to call "gtk_init()", because we don't want to have to
1068 do any X stuff just to do a build. */
1069 command_name = strrchr(ethereal_path, '/');
1070 if (command_name == NULL)
1071 command_name = ethereal_path;
1074 if (strcmp(command_name, "ethereal-dump-fields") == 0) {
1075 ethereal_proto_init();
1076 proto_registrar_dump();
1080 /* Let GTK get its args */
1081 gtk_init (&argc, &argv);
1083 prefs = read_prefs(&pf_path);
1084 if (pf_path != NULL) {
1085 /* The preferences file exists, but couldn't be opened; "pf_path" is
1086 its pathname. Remember "errno", as that says why the attempt
1088 pf_open_errno = errno;
1091 /* Initialize the capture file struct */
1093 cf.plist_end = NULL;
1098 cf.dfcode = dfilter_new();
1103 cf.save_file = NULL;
1104 cf.save_file_fd = -1;
1106 cf.snap = MAX_PACKET_SIZE;
1108 cf.cinfo.num_cols = prefs->num_cols;
1109 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
1110 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
1111 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
1112 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
1114 /* Assemble the compile-time options */
1115 snprintf(comp_info_str, 256,
1116 #ifdef GTK_MAJOR_VERSION
1117 "GTK+ %d.%d.%d, %s libpcap", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1120 "GTK+ (version unknown), %s libpcap",
1131 /* Now get our args */
1132 while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
1134 case 'b': /* Bold font */
1135 bold_font = g_strdup(optarg);
1137 case 'B': /* Byte view pane height */
1138 bv_size = atoi(optarg);
1140 case 'c': /* Capture xxx packets */
1141 cf.count = atoi(optarg);
1145 cf.cfilter = g_strdup(optarg);
1147 case 'F': /* Fork to capture */
1151 case 'h': /* Print help and exit */
1155 case 'i': /* Use interface xxx */
1156 cf.iface = g_strdup(optarg);
1158 case 'm': /* Medium font */
1159 medium_font = g_strdup(optarg);
1161 case 'n': /* No name resolution */
1162 g_resolving_actif = 0;
1165 case 'k': /* Start capture immediately */
1169 case 'P': /* Packet list pane height */
1170 pl_size = atoi(optarg);
1173 case 'Q': /* Quit after capture (just capture to file) */
1175 start_capture = 1; /*** -Q implies -k !! ***/
1178 case 'r': /* Read capture file xxx */
1179 cf_name = g_strdup(optarg);
1181 case 'R': /* Read file filter */
1185 case 's': /* Set the snapshot (capture) length */
1186 cf.snap = atoi(optarg);
1188 case 'S': /* "Sync" mode: used for following file ala tail -f */
1190 fork_mode = 1; /* -S implies -F */
1193 case 't': /* Time stamp type */
1194 if (strcmp(optarg, "r") == 0)
1195 timestamp_type = RELATIVE;
1196 else if (strcmp(optarg, "a") == 0)
1197 timestamp_type = ABSOLUTE;
1198 else if (strcmp(optarg, "d") == 0)
1199 timestamp_type = DELTA;
1201 fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
1203 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
1204 fprintf(stderr, "or \"d\" for delta.\n");
1208 case 'T': /* Tree view pane height */
1209 tv_size = atoi(optarg);
1211 case 'v': /* Show version and exit */
1212 printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
1216 case 'w': /* Write to capture file xxx */
1217 cf.save_file = g_strdup(optarg);
1219 case 'W': /* Write to capture file FD xxx */
1220 cf.save_file_fd = atoi(optarg);
1227 if (start_capture) {
1228 if (cf.iface == NULL) {
1229 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-i\" flag\n");
1232 if (cf.save_file == NULL) {
1233 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-w\" flag\n");
1237 if (cf.save_file_fd == -1) {
1238 fprintf(stderr, "ethereal: \"-k\" flag was specified with \"-%c\" flag but without \"-W\" flag\n",
1239 (sync_mode ? 'S' : 'F'));
1247 signal(SIGUSR2, sigusr2_handler);
1250 /* Build the column format array */
1251 col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
1253 for (i = 0; i < cf.cinfo.num_cols; i++) {
1254 cf.cinfo.col_fmt[i] = get_column_format(i);
1255 col_title[i] = g_strdup(get_column_title(i));
1256 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
1258 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
1259 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
1263 cf.snap = MAX_PACKET_SIZE;
1264 else if (cf.snap < MIN_PACKET_SIZE)
1265 cf.snap = MIN_PACKET_SIZE;
1267 rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4);
1268 sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE);
1269 gtk_rc_parse(rc_file);
1271 if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
1272 fprintf(stderr, "ethereal: Error font %s not found (use -m option)\n", medium_font);
1276 if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
1277 fprintf(stderr, "ethereal: Error font %s not found (use -b option)\n", bold_font);
1282 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1283 gtk_widget_set_name(window, "main window");
1284 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
1285 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
1286 gtk_signal_connect(GTK_OBJECT(window), "destroy",
1287 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
1288 gtk_signal_connect(GTK_OBJECT (window), "realize",
1289 GTK_SIGNAL_FUNC(main_realize_cb), NULL);
1290 gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer");
1291 gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1);
1292 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
1294 /* Container for menu bar, paned windows and progress/info box */
1295 main_vbox = gtk_vbox_new(FALSE, 1);
1296 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
1297 gtk_container_add(GTK_CONTAINER(window), main_vbox);
1298 gtk_widget_show(main_vbox);
1301 get_main_menu(&menubar, &accel);
1302 gtk_window_add_accel_group(GTK_WINDOW(window), accel);
1303 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
1304 gtk_widget_show(menubar);
1306 /* Panes for the packet list, tree, and byte view */
1307 u_pane = gtk_vpaned_new();
1308 gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
1309 l_pane = gtk_vpaned_new();
1310 gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
1311 gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
1312 gtk_widget_show(u_pane);
1313 gtk_paned_add2 (GTK_PANED(u_pane), l_pane);
1314 gtk_widget_show(l_pane);
1317 packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols, col_title);
1318 gtk_clist_column_titles_passive(GTK_CLIST(packet_list));
1319 packet_sw = gtk_scrolled_window_new(NULL, NULL);
1320 gtk_widget_show(packet_sw);
1321 gtk_container_add(GTK_CONTAINER(packet_sw), packet_list);
1322 pl_style = gtk_style_new();
1323 gdk_font_unref(pl_style->font);
1324 pl_style->font = m_r_font;
1325 gtk_widget_set_style(packet_list, pl_style);
1326 gtk_widget_set_name(packet_list, "packet list");
1327 gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
1328 GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
1329 gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
1330 GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
1331 for (i = 0; i < cf.cinfo.num_cols; i++) {
1332 if (get_column_resize_type(cf.cinfo.col_fmt[i]) != RESIZE_MANUAL)
1333 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1335 /* Right-justify the packet number column. */
1336 if (cf.cinfo.col_fmt[i] == COL_NUMBER)
1337 gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
1340 /* Save static column sizes to use during a "-S" capture, so that
1341 the columns don't resize during a live capture. */
1342 cf.cinfo.col_width[i] = get_column_width(get_column_format(i),
1345 gtk_widget_set_usize(packet_list, -1, pl_size);
1346 gtk_paned_add1(GTK_PANED(u_pane), packet_sw);
1347 gtk_widget_show(packet_list);
1350 tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
1351 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
1352 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1353 gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw);
1354 gtk_widget_set_usize(tv_scrollw, -1, tv_size);
1355 gtk_widget_show(tv_scrollw);
1357 tree_view = gtk_tree_new();
1358 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tv_scrollw),
1360 gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
1362 /* XXX - what's the difference between the next two lines? */
1363 gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
1364 gtk_tree_set_view_mode(GTK_TREE(tree_view), GTK_TREE_VIEW_ITEM);
1366 gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
1367 GTK_SIGNAL_FUNC(tree_view_cb), NULL);
1368 gtk_widget_show(tree_view);
1370 item_style = gtk_style_new();
1371 gdk_font_unref(item_style->font);
1372 item_style->font = m_r_font;
1375 bv_table = gtk_table_new (2, 2, FALSE);
1376 gtk_paned_add2(GTK_PANED(l_pane), bv_table);
1377 gtk_widget_set_usize(bv_table, -1, bv_size);
1378 gtk_widget_show(bv_table);
1380 byte_view = gtk_text_new(NULL, NULL);
1381 gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
1382 gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
1383 gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1,
1384 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
1385 gtk_widget_show(byte_view);
1387 bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj);
1388 gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2,
1389 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
1390 gtk_widget_show (bv_hscroll);
1392 bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
1393 gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1,
1394 GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
1395 gtk_widget_show(bv_vscroll);
1397 /* Progress/filter/info box */
1398 stat_hbox = gtk_hbox_new(FALSE, 1);
1399 gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
1400 gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
1401 gtk_widget_show(stat_hbox);
1403 prog_bar = gtk_progress_bar_new();
1404 gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
1405 gtk_widget_show(prog_bar);
1407 filter_bt = gtk_button_new_with_label("Filter:");
1408 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
1409 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
1410 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
1411 gtk_widget_show(filter_bt);
1413 filter_te = gtk_entry_new();
1414 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
1415 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_te, TRUE, TRUE, 3);
1416 gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
1417 GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
1418 gtk_widget_show(filter_te);
1420 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
1421 * of any widget that ends up calling a callback which needs
1422 * that text entry pointer */
1423 set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
1424 set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
1425 set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY,
1428 info_bar = gtk_statusbar_new();
1429 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
1430 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
1431 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
1432 gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
1433 gtk_widget_show(info_bar);
1436 Hmmm should we do it here
1439 ethereal_proto_init(); /* Init anything that needs initializing */
1441 gtk_widget_show(window);
1443 /* If we were given the name of a capture file, read it in now;
1444 we defer it until now, so that, if we can't open it, and pop
1445 up an alert box, the alert box is more likely to come up on
1446 top of the main window - but before the preference-file-error
1447 alert box, so, if we get one of those, it's more likely to come
1450 if (rfilter != NULL) {
1451 rfcode = dfilter_new();
1452 if (dfilter_compile(rfcode, rfilter) != 0) {
1453 simple_dialog(ESD_TYPE_WARN, NULL,
1454 "Unable to parse filter string \"%s\".", rfilter);
1455 dfilter_destroy(rfcode);
1456 rfilter_parse_failed = TRUE;
1459 if (!rfilter_parse_failed) {
1460 if ((err = open_cap_file(cf_name, &cf)) == 0) {
1462 err = read_cap_file(&cf);
1463 s = strrchr(cf_name, '/');
1465 last_open_dir = cf_name;
1468 set_menu_sensitivity("/File/Save As...", TRUE);
1473 /* If we failed to open the preferences file, pop up an alert box;
1474 we defer it until now, so that the alert box is more likely to
1475 come up on top of the main window. */
1476 if (pf_path != NULL) {
1477 simple_dialog(ESD_TYPE_WARN, NULL,
1478 "Can't open preferences file\n\"%s\": %s.", pf_path,
1479 strerror(pf_open_errno));