3 * $Id: ethereal.c,v 1.105 1999/08/24 17:26: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"
97 #include "gtkpacket.h"
100 static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
101 static void file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs);
102 static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
103 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
104 static void print_file_cb(GtkWidget *file_bt, gpointer file_te);
105 static void print_fs_ok_cb(GtkWidget *w, gpointer data);
106 static void print_fs_cancel_cb(GtkWidget *w, gpointer data);
107 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
108 static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
110 FILE *data_out_file = NULL;
113 GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
115 GdkFont *m_r_font, *m_b_font;
116 guint main_ctx, file_ctx;
117 gint start_capture = 0;
118 gchar comp_info_str[256];
119 gchar *ethereal_path = NULL;
120 gchar *medium_font = MONO_MEDIUM_FONT;
121 gchar *bold_font = MONO_BOLD_FONT;
122 gchar *last_open_dir = NULL;
124 ts_type timestamp_type = RELATIVE;
126 GtkStyle *item_style;
129 int sync_mode; /* allow sync */
130 int sync_pipe[2]; /* used to sync father */
131 int fork_mode; /* fork a child to do the capture */
132 int sigusr2_received = 0;
133 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
136 /* Specifies byte offsets for object selected in tree */
137 static gint tree_selected_start=-1, tree_selected_len=-1;
139 #define E_DFILTER_TE_KEY "display_filter_te"
140 #define E_RFILTER_TE_KEY "read_filter_te"
142 /* About Ethereal window */
144 about_ethereal( GtkWidget *w, gpointer data ) {
145 simple_dialog(ESD_TYPE_INFO, NULL,
146 "GNU Ethereal - network protocol analyzer\n"
147 "Version %s (C) 1998 Gerald Combs <gerald@zing.org>\n"
148 "Compiled with %s\n\n"
151 "Gilbert Ramirez <gramirez@tivoli.com>\n"
152 "Hannes R. Boehm <hannes@boehm.org>\n"
153 "Mike Hall <mlh@io.com>\n"
154 "Bobo Rajec <bobo@bsp-consulting.sk>\n"
155 "Laurent Deniel <deniel@worldnet.fr>\n"
156 "Don Lafontaine <lafont02@cn.ca>\n"
157 "Guy Harris <guy@netapp.com>\n"
158 "Simon Wilkinson <sxw@dcs.ed.ac.uk>\n"
159 "Joerg Mayer <jmayer@telemation.de>\n"
160 "Martin Maciaszek <fastjack@i-s-o.net>\n"
161 "Didier Jorand <Didier.Jorand@alcatel.fr>\n"
162 "Jun-ichiro itojun Hagino <itojun@iijlab.net>\n"
163 "Richard Sharpe <sharpe@ns.aus.com>\n"
164 "John McDermott <jjm@jkintl.com>\n"
165 "Jeff Jahr <jjahr@shastanets.com>\n"
166 "Brad Robel-Forrest <bradr@watchguard.com>\n"
167 "Ashok Narayanan <ashokn@cisco.com>\n"
168 "Aaron Hillegass <aaron@classmax.com>\n"
169 "Jason Lango <jal@netapp.com>\n"
170 "Johan Feyaerts <Johan.Feyaerts@siemens.atea.be>\n"
171 "Olivier Abad <abad@daba.dhis.org>\n"
172 "Thierry Andry <Thierry.Andry@advalvas.be>\n"
173 "Jeff Foster <jfoste@woodward.com>\n"
175 "\nSee http://ethereal.zing.org for more information",
176 VERSION, comp_info_str);
179 /* Update the progress bar */
181 file_progress_cb(gpointer p) {
182 capture_file *cf = (capture_file*) p;
183 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
184 (gfloat) ftell(cf->fh) / (gfloat) cf->f_len);
188 /* Follow the TCP stream, if any, to which the last packet that we called
189 a dissection routine on belongs (this might be the most recently
190 selected packet, or it might be the last packet in the file). */
192 follow_stream_cb( GtkWidget *w, gpointer data ) {
193 char filename1[128+1];
194 GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
198 if( pi.ipproto == 6 ) {
199 /* we got tcp so we can follow */
200 /* Create a temporary file into which to dump the reassembled data
201 from the TCP stream, and set "data_out_file" to refer to it, so
202 that the TCP code will write to it.
204 XXX - it might be nicer to just have the TCP code directly
205 append stuff to the text widget for the TCP stream window,
206 if we can arrange that said window not pop up until we're
208 tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
210 simple_dialog(ESD_TYPE_WARN, NULL,
211 "Could not create temporary file %s: %s", filename1, strerror(errno));
214 data_out_file = fdopen( tmp_fd, "w" );
215 if( data_out_file == NULL ) {
216 simple_dialog(ESD_TYPE_WARN, NULL,
217 "Could not create temporary file %s: %s", filename1, strerror(errno));
223 /* Save any display filter we currently have. */
224 old_dfilter = cf.dfilter;
226 /* Create a new filter that matches all packets in the TCP stream,
227 and set the display filter entry accordingly */
228 reset_tcp_reassembly();
229 cf.dfilter = build_follow_filter( &pi );
231 /* Run the display filter so it goes in effect. */
234 /* the data_out_file should now be full of the streams information */
235 fclose( data_out_file );
237 /* the filename1 file now has all the text that was in the session */
238 streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
239 gtk_widget_set_name( streamwindow, "TCP stream window" );
240 gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
241 NULL, "WM destroy" );
242 gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
243 NULL, "WM destroy" );
244 if( incomplete_tcp_stream ) {
245 gtk_window_set_title( GTK_WINDOW(streamwindow),
246 "Contents of TCP stream (incomplete)" );
248 gtk_window_set_title( GTK_WINDOW(streamwindow),
249 "Contents of TCP stream" );
251 gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
252 gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
254 /* setup the container */
255 box = gtk_vbox_new( FALSE, 0 );
256 gtk_container_add( GTK_CONTAINER(streamwindow), box );
257 gtk_widget_show( box );
259 /* set up the table we attach to */
260 table = gtk_table_new( 1, 2, FALSE );
261 gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
262 gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
263 gtk_widget_show( table );
265 /* create a text box */
266 text = gtk_text_new( NULL, NULL );
267 gtk_text_set_editable( GTK_TEXT(text), FALSE);
268 gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
269 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
270 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
271 gtk_widget_show(text);
273 /* create the scrollbar */
274 vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
275 gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
276 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
277 gtk_widget_show( vscrollbar );
278 gtk_widget_realize( text );
280 /* stop the updates while we fill the text box */
281 gtk_text_freeze( GTK_TEXT(text) );
282 data_out_file = fopen( filename1, "r" );
283 if( data_out_file ) {
287 nchars = fread( buffer, 1, 1024, data_out_file );
288 gtk_text_insert( GTK_TEXT(text), m_r_font, NULL, NULL, buffer, nchars );
289 if( nchars < 1024 ) {
293 if( ferror( data_out_file ) ) {
294 simple_dialog(ESD_TYPE_WARN, NULL,
295 "Error reading temporary file %s: %s", filename1, strerror(errno));
297 fclose( data_out_file );
299 simple_dialog(ESD_TYPE_WARN, NULL,
300 "Could not open temporary file %s: %s", filename1, strerror(errno));
302 gtk_text_thaw( GTK_TEXT(text) );
304 data_out_file = NULL;
305 gtk_widget_show( streamwindow );
306 if( cf.dfilter != NULL ) {
307 g_free( cf.dfilter );
309 cf.dfilter = old_dfilter;
312 simple_dialog(ESD_TYPE_WARN, NULL,
313 "Error following stream. Please make\n"
314 "sure you have a TCP packet selected.");
318 /* Match selected byte pattern */
320 match_selected_cb(GtkWidget *w, gpointer data)
322 char *buf = g_malloc(1024);
323 GtkWidget *filter_te = NULL;
328 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
330 if (tree_selected_start<0) {
331 simple_dialog(ESD_TYPE_WARN, NULL,
332 "Error determining selected bytes. Please make\n"
333 "sure you have selected a field within the tree\n"
334 "view to be matched.");
338 c = cf.pd + tree_selected_start;
341 sprintf(ptr, "frame[%d : %d] == ", tree_selected_start, tree_selected_len);
342 ptr = buf+strlen(buf);
344 if (tree_selected_len == 1) {
345 sprintf(ptr, "0x%02x", *c++);
348 for (i=0;i<tree_selected_len; i++) {
350 sprintf(ptr, "%02x", *c++);
353 sprintf(ptr, ":%02x", *c++);
355 ptr = buf+strlen(buf);
359 if( cf.dfilter != NULL ) {
360 /* get rid of this one */
361 g_free( cf.dfilter );
363 /* create a new one and set the display filter entry accordingly */
366 gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
368 /* Run the display filter so it goes in effect. */
374 file_open_cmd_cb(GtkWidget *w, gpointer data) {
375 GtkWidget *filter_hbox, *filter_bt, *filter_te;
378 chdir(last_open_dir);
380 file_sel = gtk_file_selection_new ("Ethereal: Open Capture File");
382 /* Connect the ok_button to file_open_ok_cb function and pass along a
383 pointer to the file selection box widget */
384 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
385 "clicked", (GtkSignalFunc) file_open_ok_cb, file_sel );
387 gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
388 E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
390 filter_hbox = gtk_hbox_new(FALSE, 1);
391 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
392 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_sel)->action_area),
393 filter_hbox, FALSE, FALSE, 0);
394 gtk_widget_show(filter_hbox);
396 filter_bt = gtk_button_new_with_label("Filter:");
397 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
398 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
399 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
400 gtk_widget_show(filter_bt);
402 filter_te = gtk_entry_new();
403 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
404 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
405 gtk_widget_show(filter_te);
407 gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
408 E_RFILTER_TE_KEY, filter_te);
410 /* Connect the cancel_button to destroy the widget */
411 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
412 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
413 gtk_widget_destroy, GTK_OBJECT (file_sel));
416 if( fork_mode && (cf.save_file != NULL) )
418 if( cf.save_file != NULL )
420 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), cf.save_file);
422 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
424 gtk_widget_show(file_sel);
428 file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
429 gchar *cf_name, *rfilter, *s;
430 GtkWidget *filter_te;
431 dfilter *rfcode = NULL;
434 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
435 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_RFILTER_TE_KEY);
436 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
437 if (rfilter[0] != '\0') {
438 rfcode = dfilter_new();
439 if (dfilter_compile(rfcode, rfilter) != 0) {
440 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
441 dfilter_destroy(rfcode);
446 /* Try to open the capture file. */
447 if ((err = open_cap_file(cf_name, &cf)) != 0) {
448 /* We couldn't open it; don't dismiss the open dialog box,
449 just leave it around so that the user can, after they
450 dismiss the alert box popped up for the open error,
453 dfilter_destroy(rfcode);
457 /* Attach the new read filter to "cf" ("open_cap_file()" succeeded, so
458 it closed the previous capture file, and thus destroyed any
459 previous read filter attached to "cf"). */
462 /* We've crossed the Rubicon; get rid of the file selection box. */
463 gtk_widget_hide(GTK_WIDGET (fs));
464 gtk_widget_destroy(GTK_WIDGET (fs));
466 err = read_cap_file(&cf);
467 /* Save the directory name; we can write over cf_name. */
468 s = strrchr(cf_name, '/');
469 if (s && last_open_dir) {
471 if (strcmp(last_open_dir, cf_name) != 0) {
472 g_free(last_open_dir);
473 last_open_dir = g_strdup(cf_name);
476 else if (s) { /* ! last_open_dir */
478 last_open_dir = g_strdup(cf_name);
481 last_open_dir = NULL;
483 set_menu_sensitivity("/File/Save", FALSE);
484 set_menu_sensitivity("/File/Save As...", TRUE);
490 file_close_cmd_cb(GtkWidget *widget, gpointer data) {
491 close_cap_file(&cf, info_bar, file_ctx);
495 file_save_cmd_cb(GtkWidget *w, gpointer data) {
496 file_sel = gtk_file_selection_new ("Ethereal: Save Capture File");
498 /* Connect the ok_button to file_save_ok_cb function and pass along a
499 pointer to the file selection box widget */
500 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
501 "clicked", (GtkSignalFunc) file_save_ok_cb, file_sel );
503 /* Connect the cancel_button to destroy the widget */
504 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
505 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
506 gtk_widget_destroy, GTK_OBJECT (file_sel));
508 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
510 gtk_widget_show(file_sel);
514 file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
515 file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
517 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
518 pointer to the file selection box widget */
519 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
520 "clicked", (GtkSignalFunc) file_save_as_ok_cb, file_sel );
522 /* Connect the cancel_button to destroy the widget */
523 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
524 (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
525 gtk_widget_destroy, GTK_OBJECT (file_sel));
527 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
528 gtk_widget_show(file_sel);
532 file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
536 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
537 gtk_widget_hide(GTK_WIDGET (fs));
538 gtk_widget_destroy(GTK_WIDGET (fs));
540 if (!file_mv(cf.save_file, cf_name))
543 g_free(cf.save_file);
544 cf.save_file = g_strdup(cf_name);
546 if ((err = open_cap_file(cf_name, &cf)) == 0) {
547 err = read_cap_file(&cf);
548 set_menu_sensitivity("/File/Save", FALSE);
549 set_menu_sensitivity("/File/Save As...", TRUE);
554 file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
558 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
559 gtk_widget_hide(GTK_WIDGET (fs));
560 gtk_widget_destroy(GTK_WIDGET (fs));
561 if (!file_cp(cf.filename, cf_name))
564 cf.filename = g_strdup(cf_name);
566 if ((err = open_cap_file(cf.filename, &cf)) == 0) {
567 err = read_cap_file(&cf);
568 set_menu_sensitivity("/File/Save", FALSE);
569 set_menu_sensitivity("/File/Save As...", TRUE);
573 /* Reload a file using the current read and display filters */
575 file_reload_cmd_cb(GtkWidget *w, gpointer data) {
576 /*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
577 GtkWidget *filter_te;
579 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
581 if (cf.dfilter) g_free(cf.dfilter);
582 cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
583 if (open_cap_file(cf.filename, &cf) == 0)
585 /* XXX - change the menu if the open fails? */
588 /* Run the current display filter on the current packet set, and
591 filter_activate_cb(GtkWidget *w, gpointer data)
593 char *s = gtk_entry_get_text(GTK_ENTRY(w));
598 /* simple check for empty string. XXX - need to modify to search for /^\s+$/ */
603 cf.dfilter = g_strdup(s);
610 * Remember whether we printed to a printer or a file the last time we
613 static int print_to_file;
615 /* Keys for gtk_object_set_data */
616 #define PRINT_CMD_LB_KEY "printer_command_label"
617 #define PRINT_CMD_TE_KEY "printer_command_entry"
618 #define PRINT_FILE_BT_KEY "printer_file_button"
619 #define PRINT_FILE_TE_KEY "printer_file_entry"
620 #define PRINT_DEST_RB_KEY "printer_destination_radio_button"
622 /* Print the capture */
624 file_print_cmd_cb(GtkWidget *widget, gpointer data)
627 GtkWidget *main_vb, *main_tb, *button;
629 GtkWidget *format_hb, *format_lb;
633 GtkWidget *dest_hb, *dest_lb;
634 GtkWidget *cmd_lb, *cmd_te;
635 GtkWidget *file_bt_hb, *file_bt, *file_te;
637 GtkWidget *bbox, *ok_bt, *cancel_bt;
639 /* XXX - don't pop up one if there's already one open; instead,
640 give it the input focus if that's possible. */
642 print_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
643 gtk_window_set_title(GTK_WINDOW(print_w), "Ethereal: Print");
645 /* Enclosing containers for each row of widgets */
646 main_vb = gtk_vbox_new(FALSE, 5);
647 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
648 gtk_container_add(GTK_CONTAINER(print_w), main_vb);
649 gtk_widget_show(main_vb);
651 main_tb = gtk_table_new(4, 2, FALSE);
652 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
653 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
654 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
655 gtk_widget_show(main_tb);
657 /* XXX - printing multiple frames in PostScript looks as if it's
658 tricky - you have to deal with page boundaries, I think -
659 and I'll have to spend some time learning enough about
660 PostScript to figure it out, so, for now, we only print
661 multiple frames as text. */
664 format_lb = gtk_label_new("Format:");
665 gtk_misc_set_alignment(GTK_MISC(format_lb), 1.0, 0.5);
666 gtk_table_attach_defaults(GTK_TABLE(main_tb), format_lb, 0, 1, 0, 1);
667 gtk_widget_show(format_lb);
669 format_hb = gtk_hbox_new(FALSE, 0);
670 gtk_table_attach_defaults(GTK_TABLE(main_tb), format_hb, 1, 2, 0, 1);
671 gtk_widget_show(format_hb);
673 button = gtk_radio_button_new_with_label(NULL, "Plain Text");
674 if (prefs.pr_format == PR_FMT_TEXT)
675 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
676 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
677 gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
678 gtk_widget_show(button);
680 button = gtk_radio_button_new_with_label(format_grp, "PostScript");
681 if (prefs.pr_format == PR_FMT_PS)
682 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
683 gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
684 gtk_widget_show(button);
687 /* Output destination */
688 dest_lb = gtk_label_new("Print to:");
689 gtk_misc_set_alignment(GTK_MISC(dest_lb), 1.0, 0.5);
690 gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_lb, 0, 1, 1, 2);
691 gtk_widget_show(dest_lb);
693 dest_hb = gtk_hbox_new(FALSE, 0);
694 gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_hb, 1, 2, 1, 2);
695 gtk_widget_show(dest_hb);
697 button = gtk_radio_button_new_with_label(NULL, "Command");
699 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
700 dest_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
701 gtk_box_pack_start(GTK_BOX(dest_hb), button, FALSE, FALSE, 10);
702 gtk_widget_show(button);
704 dest_rb = gtk_radio_button_new_with_label(dest_grp, "File");
706 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_rb), TRUE);
707 gtk_signal_connect(GTK_OBJECT(dest_rb), "toggled",
708 GTK_SIGNAL_FUNC(print_cmd_toggle_dest), NULL);
709 gtk_box_pack_start(GTK_BOX(dest_hb), dest_rb, FALSE, FALSE, 10);
710 gtk_widget_show(dest_rb);
712 /* Command text entry */
713 cmd_lb = gtk_label_new("Command:");
714 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_LB_KEY, cmd_lb);
715 gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
716 gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_lb, 0, 1, 2, 3);
717 gtk_widget_set_sensitive(cmd_lb, !print_to_file);
718 gtk_widget_show(cmd_lb);
720 cmd_te = gtk_entry_new();
721 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_TE_KEY, cmd_te);
723 gtk_entry_set_text(GTK_ENTRY(cmd_te), prefs.pr_cmd);
724 gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_te, 1, 2, 2, 3);
725 gtk_widget_set_sensitive(cmd_te, !print_to_file);
726 gtk_widget_show(cmd_te);
728 /* File button and text entry */
729 file_bt_hb = gtk_hbox_new(FALSE, 0);
730 gtk_table_attach_defaults(GTK_TABLE(main_tb), file_bt_hb, 0, 1, 3, 4);
731 gtk_widget_show(file_bt_hb);
733 file_bt = gtk_button_new_with_label("File:");
734 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_BT_KEY, file_bt);
735 gtk_box_pack_end(GTK_BOX(file_bt_hb), file_bt, FALSE, FALSE, 0);
736 gtk_widget_set_sensitive(file_bt, print_to_file);
737 gtk_widget_show(file_bt);
739 file_te = gtk_entry_new();
740 gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_TE_KEY, file_te);
741 gtk_table_attach_defaults(GTK_TABLE(main_tb), file_te, 1, 2, 3, 4);
742 gtk_widget_set_sensitive(file_te, print_to_file);
743 gtk_widget_show(file_te);
745 gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
746 GTK_SIGNAL_FUNC(print_file_cb), GTK_OBJECT(file_te));
748 /* Button row: OK and Cancel buttons */
749 bbox = gtk_hbutton_box_new();
750 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
751 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
752 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
753 gtk_widget_show(bbox);
755 ok_bt = gtk_button_new_with_label ("OK");
756 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_DEST_RB_KEY, dest_rb);
757 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
758 gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
759 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
760 GTK_SIGNAL_FUNC(print_ok_cb), GTK_OBJECT(print_w));
761 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
762 gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
763 gtk_widget_grab_default(ok_bt);
764 gtk_widget_show(ok_bt);
766 cancel_bt = gtk_button_new_with_label ("Cancel");
767 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
768 GTK_SIGNAL_FUNC(print_close_cb), GTK_OBJECT(print_w));
769 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
770 gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
771 gtk_widget_show(cancel_bt);
774 display_opt_window_active = TRUE;
776 gtk_widget_show(print_w);
780 print_cmd_toggle_dest(GtkWidget *widget, gpointer data)
782 GtkWidget *cmd_lb, *cmd_te, *file_bt, *file_te;
785 cmd_lb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
787 cmd_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
789 file_bt = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
791 file_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
793 if (GTK_TOGGLE_BUTTON (widget)->active) {
794 /* They selected "Print to File" */
797 /* They selected "Print to Command" */
800 gtk_widget_set_sensitive(cmd_lb, !to_file);
801 gtk_widget_set_sensitive(cmd_te, !to_file);
802 gtk_widget_set_sensitive(file_bt, to_file);
803 gtk_widget_set_sensitive(file_te, to_file);
807 print_file_cb(GtkWidget *file_bt, gpointer file_te)
811 fs = gtk_file_selection_new ("Ethereal: Print to File");
812 gtk_object_set_data(GTK_OBJECT(fs), PRINT_FILE_TE_KEY, file_te);
814 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
815 "clicked", (GtkSignalFunc) print_fs_ok_cb, fs);
817 /* Connect the cancel_button to destroy the widget */
818 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
819 "clicked", (GtkSignalFunc) print_fs_cancel_cb, fs);
825 print_fs_ok_cb(GtkWidget *w, gpointer data)
828 gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
830 gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
831 gtk_widget_destroy(GTK_WIDGET(data));
835 print_fs_cancel_cb(GtkWidget *w, gpointer data)
837 gtk_widget_destroy(GTK_WIDGET(data));
841 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
846 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
848 if (GTK_TOGGLE_BUTTON (button)->active)
849 print_to_file = TRUE;
851 print_to_file = FALSE;
854 dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
855 PRINT_FILE_TE_KEY))));
857 dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
858 PRINT_CMD_TE_KEY))));
860 gtk_widget_destroy(GTK_WIDGET(parent_w));
862 display_opt_window_active = FALSE;
865 /* Now print the packets */
866 if (!print_packets(&cf, print_to_file, dest)) {
868 simple_dialog(ESD_TYPE_WARN, NULL,
869 file_write_error_message(errno), dest);
871 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
879 print_close_cb(GtkWidget *close_bt, gpointer parent_w)
882 gtk_grab_remove(GTK_WIDGET(parent_w));
883 gtk_widget_destroy(GTK_WIDGET(parent_w));
885 display_opt_window_active = FALSE;
891 file_print_packet_cmd_cb(GtkWidget *widget, gpointer data) {
894 switch (prefs.pr_dest) {
897 fh = popen(prefs.pr_cmd, "w");
901 fh = fopen(prefs.pr_file, "w");
905 fh = NULL; /* XXX - "can't happen" */
909 switch (prefs.pr_dest) {
912 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
917 simple_dialog(ESD_TYPE_WARN, NULL, file_write_error_message(errno),
925 proto_tree_print(-1, (GNode*) cf.protocol_tree, cf.pd, cf.fd, fh);
927 close_print_dest(prefs.pr_dest == PR_DEST_FILE, fh);
930 /* What to do when a list item is selected/unselected */
932 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
943 select_packet(&cf, row);
947 packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
948 unselect_packet(&cf);
952 tree_view_cb(GtkWidget *w, gpointer data) {
954 tree_selected_start = -1;
955 tree_selected_len = -1;
957 if (GTK_TREE(w)->selection) {
958 tree_selected_start =
959 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
960 E_TREEINFO_START_KEY);
962 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
966 gtk_text_freeze(GTK_TEXT(byte_view));
967 gtk_text_set_point(GTK_TEXT(byte_view), 0);
968 gtk_text_forward_delete(GTK_TEXT(byte_view),
969 gtk_text_get_length(GTK_TEXT(byte_view)));
970 packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.fd->cap_len,
974 gtk_text_thaw(GTK_TEXT(byte_view));
978 file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
979 if (cf.save_file && !cf.user_saved) {
980 unlink(cf.save_file);
985 void blank_packetinfo() {
993 /* Things to do when the main window is realized */
995 main_realize_cb(GtkWidget *w, gpointer data) {
1006 sigusr2_handler(int sig) {
1007 sigusr2_received = 1;
1008 signal(SIGUSR2, sigusr2_handler);
1012 /* call initialization routines at program startup time */
1014 ethereal_proto_init(void) {
1023 fprintf(stderr, "This is GNU %s %s, compiled with %s\n", PACKAGE,
1024 VERSION, comp_info_str);
1025 fprintf(stderr, "%s [-vh] [-FkQS] [-b bold font] [-B byte view height] [-c count]\n",
1027 fprintf(stderr, " [-f \"filter expression\"] [-i interface] [-m medium font] [-n]\n");
1028 fprintf(stderr, " [-P packet list height] [-r infile] [-s snaplen]\n");
1029 fprintf(stderr, " [-t <time stamp format>] [-T tree view height] [-w savefile] \n");
1032 /* And now our feature presentation... [ fade to music ] */
1034 main(int argc, char *argv[])
1036 char *command_name, *s;
1040 extern char *optarg;
1043 int pf_open_errno = 0;
1045 GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane,
1046 *bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox,
1047 *tv_scrollw, *filter_bt, *filter_te;
1049 GtkAccelGroup *accel;
1050 GtkWidget *packet_sw;
1051 gint pl_size = 280, tv_size = 95, bv_size = 75;
1052 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1053 dfilter *rfcode = NULL;
1054 gboolean rfilter_parse_failed = FALSE;
1058 ethereal_path = argv[0];
1060 /* If invoked as "ethereal-dump-fields", we dump out a glossary of
1061 display filter symbols; we specify that by checking the name,
1062 so that we can do so before looking at the argument list -
1063 we don't want to look at the argument list, because we don't
1064 want to call "gtk_init()", because we don't want to have to
1065 do any X stuff just to do a build. */
1066 command_name = strrchr(ethereal_path, '/');
1067 if (command_name == NULL)
1068 command_name = ethereal_path;
1071 if (strcmp(command_name, "ethereal-dump-fields") == 0) {
1072 ethereal_proto_init();
1073 proto_registrar_dump();
1077 /* Let GTK get its args */
1078 gtk_init (&argc, &argv);
1080 prefs = read_prefs(&pf_path);
1081 if (pf_path != NULL) {
1082 /* The preferences file exists, but couldn't be opened; "pf_path" is
1083 its pathname. Remember "errno", as that says why the attempt
1085 pf_open_errno = errno;
1088 /* Initialize the capture file struct */
1090 cf.plist_end = NULL;
1095 cf.dfcode = dfilter_new();
1100 cf.save_file = NULL;
1101 cf.save_file_fd = -1;
1103 cf.snap = WTAP_MAX_PACKET_SIZE;
1105 cf.cinfo.num_cols = prefs->num_cols;
1106 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
1107 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
1108 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
1109 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
1111 /* Assemble the compile-time options */
1112 snprintf(comp_info_str, 256,
1113 #ifdef GTK_MAJOR_VERSION
1114 "GTK+ %d.%d.%d, %s libpcap", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1117 "GTK+ (version unknown), %s libpcap",
1128 /* Now get our args */
1129 while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
1131 case 'b': /* Bold font */
1132 bold_font = g_strdup(optarg);
1134 case 'B': /* Byte view pane height */
1135 bv_size = atoi(optarg);
1137 case 'c': /* Capture xxx packets */
1138 cf.count = atoi(optarg);
1142 cf.cfilter = g_strdup(optarg);
1144 case 'F': /* Fork to capture */
1148 case 'h': /* Print help and exit */
1152 case 'i': /* Use interface xxx */
1153 cf.iface = g_strdup(optarg);
1155 case 'm': /* Medium font */
1156 medium_font = g_strdup(optarg);
1158 case 'n': /* No name resolution */
1159 g_resolving_actif = 0;
1162 case 'k': /* Start capture immediately */
1166 case 'P': /* Packet list pane height */
1167 pl_size = atoi(optarg);
1170 case 'Q': /* Quit after capture (just capture to file) */
1172 start_capture = 1; /*** -Q implies -k !! ***/
1175 case 'r': /* Read capture file xxx */
1176 cf_name = g_strdup(optarg);
1178 case 'R': /* Read file filter */
1182 case 's': /* Set the snapshot (capture) length */
1183 cf.snap = atoi(optarg);
1185 case 'S': /* "Sync" mode: used for following file ala tail -f */
1187 fork_mode = 1; /* -S implies -F */
1190 case 't': /* Time stamp type */
1191 if (strcmp(optarg, "r") == 0)
1192 timestamp_type = RELATIVE;
1193 else if (strcmp(optarg, "a") == 0)
1194 timestamp_type = ABSOLUTE;
1195 else if (strcmp(optarg, "d") == 0)
1196 timestamp_type = DELTA;
1198 fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
1200 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
1201 fprintf(stderr, "or \"d\" for delta.\n");
1205 case 'T': /* Tree view pane height */
1206 tv_size = atoi(optarg);
1208 case 'v': /* Show version and exit */
1209 printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
1213 case 'w': /* Write to capture file xxx */
1214 cf.save_file = g_strdup(optarg);
1216 case 'W': /* Write to capture file FD xxx */
1217 cf.save_file_fd = atoi(optarg);
1224 if (start_capture) {
1225 if (cf.iface == NULL) {
1226 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-i\" flag\n");
1229 if (cf.save_file == NULL) {
1230 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-w\" flag\n");
1235 if (cf.save_file_fd == -1) {
1236 fprintf(stderr, "ethereal: \"-k\" flag was specified with \"-%c\" flag but without \"-W\" flag\n",
1237 (sync_mode ? 'S' : 'F'));
1246 signal(SIGUSR2, sigusr2_handler);
1249 /* Build the column format array */
1250 col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
1252 for (i = 0; i < cf.cinfo.num_cols; i++) {
1253 cf.cinfo.col_fmt[i] = get_column_format(i);
1254 col_title[i] = g_strdup(get_column_title(i));
1255 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
1257 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
1258 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
1262 cf.snap = WTAP_MAX_PACKET_SIZE;
1263 else if (cf.snap < MIN_PACKET_SIZE)
1264 cf.snap = MIN_PACKET_SIZE;
1266 rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4);
1267 sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE);
1268 gtk_rc_parse(rc_file);
1270 if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
1271 fprintf(stderr, "ethereal: Error font %s not found (use -m option)\n", medium_font);
1275 if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
1276 fprintf(stderr, "ethereal: Error font %s not found (use -b option)\n", bold_font);
1281 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1282 gtk_widget_set_name(window, "main window");
1283 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
1284 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
1285 gtk_signal_connect(GTK_OBJECT(window), "destroy",
1286 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
1287 gtk_signal_connect(GTK_OBJECT (window), "realize",
1288 GTK_SIGNAL_FUNC(main_realize_cb), NULL);
1289 gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer");
1290 gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1);
1291 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
1293 /* Container for menu bar, paned windows and progress/info box */
1294 main_vbox = gtk_vbox_new(FALSE, 1);
1295 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
1296 gtk_container_add(GTK_CONTAINER(window), main_vbox);
1297 gtk_widget_show(main_vbox);
1300 get_main_menu(&menubar, &accel);
1301 gtk_window_add_accel_group(GTK_WINDOW(window), accel);
1302 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
1303 gtk_widget_show(menubar);
1305 /* Panes for the packet list, tree, and byte view */
1306 u_pane = gtk_vpaned_new();
1307 gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
1308 l_pane = gtk_vpaned_new();
1309 gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
1310 gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
1311 gtk_widget_show(u_pane);
1312 gtk_paned_add2 (GTK_PANED(u_pane), l_pane);
1313 gtk_widget_show(l_pane);
1316 packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols, col_title);
1317 gtk_clist_column_titles_passive(GTK_CLIST(packet_list));
1318 packet_sw = gtk_scrolled_window_new(NULL, NULL);
1319 gtk_widget_show(packet_sw);
1320 gtk_container_add(GTK_CONTAINER(packet_sw), packet_list);
1321 pl_style = gtk_style_new();
1322 gdk_font_unref(pl_style->font);
1323 pl_style->font = m_r_font;
1324 gtk_widget_set_style(packet_list, pl_style);
1325 gtk_widget_set_name(packet_list, "packet list");
1326 gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
1327 GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
1328 gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
1329 GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
1330 for (i = 0; i < cf.cinfo.num_cols; i++) {
1331 if (get_column_resize_type(cf.cinfo.col_fmt[i]) != RESIZE_MANUAL)
1332 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1334 /* Right-justify the packet number column. */
1335 if (cf.cinfo.col_fmt[i] == COL_NUMBER)
1336 gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
1339 /* Save static column sizes to use during a "-S" capture, so that
1340 the columns don't resize during a live capture. */
1341 cf.cinfo.col_width[i] = get_column_width(get_column_format(i),
1344 gtk_widget_set_usize(packet_list, -1, pl_size);
1345 gtk_paned_add1(GTK_PANED(u_pane), packet_sw);
1346 gtk_widget_show(packet_list);
1349 tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
1350 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
1351 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1352 gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw);
1353 gtk_widget_set_usize(tv_scrollw, -1, tv_size);
1354 gtk_widget_show(tv_scrollw);
1356 tree_view = gtk_tree_new();
1357 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tv_scrollw),
1359 gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
1361 /* XXX - what's the difference between the next two lines? */
1362 gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
1363 gtk_tree_set_view_mode(GTK_TREE(tree_view), GTK_TREE_VIEW_ITEM);
1365 gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
1366 GTK_SIGNAL_FUNC(tree_view_cb), NULL);
1367 gtk_widget_show(tree_view);
1369 item_style = gtk_style_new();
1370 gdk_font_unref(item_style->font);
1371 item_style->font = m_r_font;
1374 bv_table = gtk_table_new (2, 2, FALSE);
1375 gtk_paned_add2(GTK_PANED(l_pane), bv_table);
1376 gtk_widget_set_usize(bv_table, -1, bv_size);
1377 gtk_widget_show(bv_table);
1379 byte_view = gtk_text_new(NULL, NULL);
1380 gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
1381 gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
1382 gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1,
1383 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
1384 gtk_widget_show(byte_view);
1386 bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj);
1387 gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2,
1388 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
1389 gtk_widget_show (bv_hscroll);
1391 bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
1392 gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1,
1393 GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
1394 gtk_widget_show(bv_vscroll);
1396 /* Progress/filter/info box */
1397 stat_hbox = gtk_hbox_new(FALSE, 1);
1398 gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
1399 gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
1400 gtk_widget_show(stat_hbox);
1402 prog_bar = gtk_progress_bar_new();
1403 gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
1404 gtk_widget_show(prog_bar);
1406 filter_bt = gtk_button_new_with_label("Filter:");
1407 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
1408 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
1409 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
1410 gtk_widget_show(filter_bt);
1412 filter_te = gtk_entry_new();
1413 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
1414 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_te, TRUE, TRUE, 3);
1415 gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
1416 GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
1417 gtk_widget_show(filter_te);
1419 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
1420 * of any widget that ends up calling a callback which needs
1421 * that text entry pointer */
1422 set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
1423 set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
1424 set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY,
1427 info_bar = gtk_statusbar_new();
1428 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
1429 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
1430 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
1431 gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
1432 gtk_widget_show(info_bar);
1435 Hmmm should we do it here
1438 ethereal_proto_init(); /* Init anything that needs initializing */
1440 gtk_widget_show(window);
1444 /* If we were given the name of a capture file, read it in now;
1445 we defer it until now, so that, if we can't open it, and pop
1446 up an alert box, the alert box is more likely to come up on
1447 top of the main window - but before the preference-file-error
1448 alert box, so, if we get one of those, it's more likely to come
1451 if (rfilter != NULL) {
1452 rfcode = dfilter_new();
1453 if (dfilter_compile(rfcode, rfilter) != 0) {
1454 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
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));