5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@ethereal.com>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
11 * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 * - Multiple window support
33 * - Add cut/copy/paste
34 * - Create header parsing routines
35 * - Make byte view selections more fancy?
56 #include <io.h> /* open/close on win32 */
59 #ifdef NEED_STRERROR_H
67 #ifdef _WIN32 /* Needed for console I/O */
72 #include <epan/epan.h>
73 #include <epan/filesystem.h>
74 #include <epan/epan_dissect.h>
75 #include <epan/timestamp.h>
76 #include <epan/packet.h>
77 #include <epan/plugins.h>
78 #include <epan/dfilter/dfilter.h>
79 #include <epan/strutil.h>
80 #include <epan/addr_resolv.h>
82 /* general (not GTK specific) */
83 #include "svnversion.h"
87 #include "disabled_protos.h"
88 #include <epan/prefs.h>
89 #include "filter_dlg.h"
90 #include "layout_prefs.h"
92 #include "color_filters.h"
94 #include "simple_dialog.h"
96 #include <epan/prefs-int.h>
97 #include "ringbuffer.h"
98 #include "../ui_util.h" /* beware: ui_util.h exists twice! */
101 #include "clopts_common.h"
102 #include "version_info.h"
106 #include "pcap-util.h"
109 #include "capture-wpcap.h"
111 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
112 #include "ethclist.h"
116 #include "statusbar.h"
117 #include "alert_box.h"
118 #include "dlg_utils.h"
119 #include "gtkglobals.h"
121 #include "ui_util.h" /* beware: ui_util.h exists twice! */
122 #include "compat_macros.h"
127 #include "file_dlg.h"
128 #include <epan/column.h>
129 #include "proto_draw.h"
131 #include "packet_win.h"
133 #include "find_dlg.h"
134 #include "packet_list.h"
136 #include "follow_dlg.h"
137 #include "font_utils.h"
138 #include "about_dlg.h"
139 #include "help_dlg.h"
140 #include "decode_as_dlg.h"
144 * File under personal preferences directory in which GTK settings for
145 * Ethereal are stored.
147 #define RC_FILE "gtkrc"
150 #define DEF_READY_MESSAGE " Ready to load or capture"
152 #define DEF_READY_MESSAGE " Ready to load file"
156 GtkWidget *main_display_filter_widget=NULL;
157 GtkWidget *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
158 static GtkWidget *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
159 static GtkWidget *main_first_pane, *main_second_pane;
160 static GtkWidget *status_pane;
161 static GtkWidget *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
162 static GtkWidget *info_bar;
163 static GtkWidget *packets_bar = NULL;
164 static guint main_ctx, file_ctx, help_ctx;
165 static guint packets_ctx;
166 static gchar *packets_str = NULL;
167 GString *comp_info_str, *runtime_info_str;
168 gchar *ethereal_path = NULL;
171 static gboolean has_console; /* TRUE if app has console */
172 /*static void create_console(void);*/
173 static void destroy_console(void);
174 static void console_log_handler(const char *log_domain,
175 GLogLevelFlags log_level, const char *message, gpointer user_data);
179 static gboolean list_link_layer_types;
182 static void create_main_window(gint, gint, gint, e_prefs*);
183 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_);
184 static void main_save_window_geometry(GtkWidget *widget);
186 #define E_DFILTER_CM_KEY "display_filter_combo"
187 #define E_DFILTER_FL_KEY "display_filter_list"
191 /* Match selected byte pattern */
193 match_selected_cb_do(gpointer data, int action, gchar *text)
195 GtkWidget *filter_te;
196 char *cur_filter, *new_filter;
201 filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
204 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
206 switch (action&MATCH_SELECTED_MASK) {
208 case MATCH_SELECTED_REPLACE:
209 new_filter = g_strdup(text);
212 case MATCH_SELECTED_AND:
213 if ((!cur_filter) || (0 == strlen(cur_filter)))
214 new_filter = g_strdup(text);
216 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
219 case MATCH_SELECTED_OR:
220 if ((!cur_filter) || (0 == strlen(cur_filter)))
221 new_filter = g_strdup(text);
223 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
226 case MATCH_SELECTED_NOT:
227 new_filter = g_strconcat("!(", text, ")", NULL);
230 case MATCH_SELECTED_AND_NOT:
231 if ((!cur_filter) || (0 == strlen(cur_filter)))
232 new_filter = g_strconcat("!(", text, ")", NULL);
234 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
237 case MATCH_SELECTED_OR_NOT:
238 if ((!cur_filter) || (0 == strlen(cur_filter)))
239 new_filter = g_strconcat("!(", text, ")", NULL);
241 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
245 g_assert_not_reached();
250 /* Free up the copy we got of the old filter text. */
253 /* create a new one and set the display filter entry accordingly */
254 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
256 /* Run the display filter so it goes in effect. */
257 if (action&MATCH_SELECTED_APPLY_NOW)
258 main_filter_packets(&cfile, new_filter, FALSE);
260 /* Free up the new filter text. */
263 /* Free up the generated text we were handed. */
268 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
270 if (cfile.finfo_selected)
271 match_selected_cb_do((data ? data : w),
273 proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
278 get_text_from_packet_list(gpointer data)
280 gint row = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY));
281 gint column = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY));
282 frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
290 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
291 cfile.pd, fdata->cap_len, &err, &err_info)) {
292 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
293 cf_read_error_message(err, err_info), cfile.filename);
297 edt = epan_dissect_new(FALSE, FALSE);
298 epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
300 epan_dissect_fill_in_columns(edt);
302 if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
303 strlen(cfile.cinfo.col_expr_val[column]) != 0) {
304 len = strlen(cfile.cinfo.col_expr[column]) +
305 strlen(cfile.cinfo.col_expr_val[column]) + 5;
306 buf = g_malloc0(len);
307 g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
308 cfile.cinfo.col_expr_val[column]);
311 epan_dissect_free(edt);
318 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
320 match_selected_cb_do(data,
322 get_text_from_packet_list(data));
327 /* XXX: use a preference for this setting! */
328 static guint dfilter_combo_max_recent = 10;
330 /* add a display filter to the combo box */
331 /* Note: a new filter string will replace an old identical one */
333 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
335 GList *filter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
338 /* GtkCombos don't let us get at their list contents easily, so we maintain
339 our own filter list, and feed it to gtk_combo_set_popdown_strings when
340 a new filter is added. */
341 li = g_list_first(filter_list);
343 /* If the filter is already in the list, remove the old one and
344 * append the new one at the latest position (at g_list_append() below) */
345 if (li->data && strcmp(s, li->data) == 0) {
346 filter_list = g_list_remove(filter_list, li->data);
352 filter_list = g_list_append(filter_list, s);
353 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, filter_list);
354 gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
355 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), g_list_last(filter_list)->data);
361 /* write all non empty display filters (until maximum count)
362 * of the combo box GList to the user's recent file */
364 dfilter_recent_combo_write_all(FILE *rf) {
365 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
366 GList *filter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
371 /* write all non empty display filter strings to the recent file (until max count) */
372 li = g_list_first(filter_list);
373 while ( li && (max_count++ <= dfilter_combo_max_recent) ) {
374 if (strlen(li->data)) {
375 fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", (char *)li->data);
381 /* empty the combobox entry field */
383 dfilter_combo_add_empty(void) {
384 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
386 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), "");
390 /* add a display filter coming from the user's recent file to the dfilter combo box */
392 dfilter_combo_add_recent(gchar *s) {
393 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
397 if (!dfilter_combo_add(filter_cm, dup)) {
406 /* call filter_packets() and add this filter string to the recent filter list */
408 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
410 GtkCombo *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
411 GList *filter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
413 gboolean add_filter = TRUE;
414 gboolean free_filter = TRUE;
416 gboolean filter_packets_ret;
418 s = g_strdup(dftext);
420 /* GtkCombos don't let us get at their list contents easily, so we maintain
421 our own filter list, and feed it to gtk_combo_set_popdown_strings when
422 a new filter is added. */
423 if ((filter_packets_ret = filter_packets(cf, s, force))) {
424 li = g_list_first(filter_list);
426 if (li->data && strcmp(s, li->data) == 0)
432 /* trim list size first */
433 while (g_list_length(filter_list) >= dfilter_combo_max_recent) {
434 filter_list = g_list_remove(filter_list, g_list_first(filter_list)->data);
438 filter_list = g_list_append(filter_list, s);
439 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, filter_list);
440 gtk_combo_set_popdown_strings(filter_cm, filter_list);
441 gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(filter_list)->data);
447 return filter_packets_ret;
451 /* Run the current display filter on the current packet set, and
454 filter_activate_cb(GtkWidget *w _U_, gpointer data)
458 s = gtk_entry_get_text(GTK_ENTRY(data));
460 main_filter_packets(&cfile, s, FALSE);
463 /* redisplay with no display filter */
465 filter_reset_cb(GtkWidget *w, gpointer data _U_)
467 GtkWidget *filter_te = NULL;
469 if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
470 gtk_entry_set_text(GTK_ENTRY(filter_te), "");
472 main_filter_packets(&cfile, "", FALSE);
475 /* mark as reference time frame */
477 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
481 frame->flags.ref_time=1;
483 frame->flags.ref_time=0;
485 reftime_packets(&cfile);
489 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
494 if (cfile.current_frame) {
495 /* XXX hum, should better have a "cfile->current_row" here ... */
496 set_frame_reftime(!cfile.current_frame->flags.ref_time,
498 packet_list_find_row_from_data(cfile.current_frame));
501 case REFTIME_FIND_NEXT:
502 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
504 case REFTIME_FIND_PREV:
505 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
510 #if GTK_MAJOR_VERSION < 2
512 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
513 gpointer user_data _U_)
516 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
520 gchar *help_str = NULL;
521 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
523 gboolean has_blurb = FALSE;
524 guint length = 0, byte_len;
525 GtkWidget *byte_view;
526 const guint8 *byte_data;
527 #if GTK_MAJOR_VERSION >= 2
532 #if GTK_MAJOR_VERSION >= 2
533 /* if nothing is selected */
534 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
537 * Which byte view is displaying the current protocol tree
540 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
541 if (byte_view == NULL)
544 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
545 if (byte_data == NULL)
548 unselect_field(&cfile);
549 packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
550 cfile.current_frame, NULL, byte_len);
553 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
556 finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
560 set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
562 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
563 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
564 g_assert(byte_data != NULL);
566 cfile.finfo_selected = finfo;
567 set_menus_for_selected_tree_row(&cfile);
570 if (finfo->hfinfo->blurb != NULL &&
571 finfo->hfinfo->blurb[0] != '\0') {
573 length = strlen(finfo->hfinfo->blurb);
575 length = strlen(finfo->hfinfo->name);
577 if (finfo->length == 0) {
579 } else if (finfo->length == 1) {
580 strcpy (len_str, ", 1 byte");
582 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
584 statusbar_pop_field_msg(); /* get rid of current help msg */
586 help_str = g_strdup_printf("%s (%s)%s",
587 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
588 finfo->hfinfo->abbrev, len_str);
589 statusbar_push_field_msg(help_str);
593 * Don't show anything if the field name is zero-length;
594 * the pseudo-field for "proto_tree_add_text()" is such
595 * a field, and we don't want "Text (text)" showing up
596 * on the status line if you've selected such a field.
598 * XXX - there are zero-length fields for which we *do*
599 * want to show the field name.
601 * XXX - perhaps the name and abbrev field should be null
602 * pointers rather than null strings for that pseudo-field,
603 * but we'd have to add checks for null pointers in some
604 * places if we did that.
606 * Or perhaps protocol tree items added with
607 * "proto_tree_add_text()" should have -1 as the field index,
608 * with no pseudo-field being used, but that might also
609 * require special checks for -1 to be added.
611 statusbar_push_field_msg("");
615 #if GTK_MAJOR_VERSION < 2
616 packet_hex_print(GTK_TEXT(byte_view), byte_data, cfile.current_frame,
619 packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data, cfile.current_frame,
624 #if GTK_MAJOR_VERSION < 2
626 tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
627 gpointer user_data _U_)
629 GtkWidget *byte_view;
634 * Which byte view is displaying the current protocol tree
637 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
638 if (byte_view == NULL)
641 data = get_byte_view_data_and_length(byte_view, &len);
645 unselect_field(&cfile);
646 packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
651 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
653 collapse_all_tree(cfile.edt->tree, tree_view);
656 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
658 expand_all_tree(cfile.edt->tree, tree_view);
661 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
662 #if GTK_MAJOR_VERSION < 2
668 #if GTK_MAJOR_VERSION < 2
669 node = gtk_ctree_find_by_row_data(GTK_CTREE(tree_view), NULL, cfile.finfo_selected);
671 gtk_ctree_expand_recursive(GTK_CTREE(tree_view), node);
673 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
675 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
676 gtk_tree_path_free(path);
680 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
681 if (cfile.edt->tree) {
682 guint32 tmp = g_resolv_flags;
683 g_resolv_flags = RESOLV_ALL;
684 proto_tree_draw(cfile.edt->tree, tree_view);
685 g_resolv_flags = tmp;
690 * Push a message referring to file access onto the statusbar.
693 statusbar_push_file_msg(gchar *msg)
695 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
699 * Pop a message referring to file access off the statusbar.
702 statusbar_pop_file_msg(void)
704 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
708 * XXX - do we need multiple statusbar contexts?
712 * Push a message referring to the currently-selected field onto the statusbar.
715 statusbar_push_field_msg(gchar *msg)
717 gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
721 * Pop a message referring to the currently-selected field off the statusbar.
724 statusbar_pop_field_msg(void)
726 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
730 * update the packets statusbar to the current values
732 void packets_bar_update(void)
736 /* remove old status */
739 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
742 /* do we have any packets? */
744 packets_str = g_strdup_printf(" P: %u D: %u M: %u",
745 cfile.count, cfile.displayed_count, cfile.marked_count);
747 packets_str = g_strdup(" No Packets");
749 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
760 /* get the current geometry, before writing it to disk */
761 main_save_window_geometry(top_level);
763 /* write user's recent file to disk
764 * It is no problem to write this file, even if we do not quit */
765 write_recent(&rec_path);
767 /* XXX - should we check whether the capture file is an
768 unsaved temporary file for a live capture and, if so,
769 pop up a "do you want to exit without saving the capture
770 file?" dialog, and then just return, leaving said dialog
771 box to forcibly quit if the user clicks "OK"?
773 If so, note that this should be done in a subroutine that
774 returns TRUE if we do so, and FALSE otherwise, and if it
775 returns TRUE we should return TRUE without nuking anything.
777 Note that, if we do that, we might also want to check if
778 an "Update list of packets in real time" capture is in
779 progress and, if so, ask whether they want to terminate
780 the capture and discard it, and return TRUE, before nuking
781 any child capture, if they say they don't want to do so. */
784 /* Nuke any child capture in progress. */
785 kill_capture_child();
788 /* Are we in the middle of reading a capture? */
789 if (cfile.state == FILE_READ_IN_PROGRESS) {
790 /* Yes, so we can't just close the file and quit, as
791 that may yank the rug out from under the read in
792 progress; instead, just set the state to
793 "FILE_READ_ABORTED" and return - the code doing the read
794 will check for that and, if it sees that, will clean
796 cfile.state = FILE_READ_ABORTED;
798 /* Say that the window should *not* be deleted;
799 that'll be done by the code that cleans up. */
802 /* Close any capture file we have open; on some OSes, you
803 can't unlink a temporary capture file if you have it
805 "cf_close()" will unlink it after closing it if
806 it's a temporary file.
808 We do this here, rather than after the main loop returns,
809 as, after the main loop returns, the main window may have
810 been destroyed (if this is called due to a "destroy"
811 even on the main window rather than due to the user
812 selecting a menu item), and there may be a crash
813 or other problem when "cf_close()" tries to
814 clean up stuff in the main window.
816 XXX - is there a better place to put this?
817 Or should we have a routine that *just* closes the
818 capture file, and doesn't do anything with the UI,
819 which we'd call here, and another routine that
820 calls that routine and also cleans up the UI, which
821 we'd call elsewhere? */
824 /* Exit by leaving the main loop, so that any quit functions
825 we registered get called. */
828 /* Say that the window should be deleted. */
834 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
838 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
839 #if GTK_MAJOR_VERSION >= 2
840 gtk_window_present(GTK_WINDOW(top_level));
842 /* user didn't saved his current file, ask him */
843 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
844 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
845 "If you quit the program without saving, your capture data will be discarded.");
846 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
849 /* unchanged file, just exit */
850 /* "main_do_quit()" indicates whether the main window should be deleted. */
851 return main_do_quit();
858 main_load_window_geometry(GtkWidget *widget)
860 window_geometry_t geom;
862 geom.set_pos = prefs.gui_geometry_save_position;
863 geom.x = recent.gui_geometry_main_x;
864 geom.y = recent.gui_geometry_main_y;
865 geom.set_size = prefs.gui_geometry_save_size;
866 if (recent.gui_geometry_main_width > 0 &&
867 recent.gui_geometry_main_height > 0) {
868 geom.width = recent.gui_geometry_main_width;
869 geom.height = recent.gui_geometry_main_height;
870 geom.set_maximized = prefs.gui_geometry_save_maximized;
872 /* We assume this means the width and height weren't set in
873 the "recent" file (or that there is no "recent" file),
874 and weren't set to a default value, so we don't set the
875 size. (The "recent" file code rejects non-positive width
876 and height values.) */
877 geom.set_size = FALSE;
879 geom.maximized = recent.gui_geometry_main_maximized;
881 window_set_geometry(widget, &geom);
883 #if GTK_MAJOR_VERSION >= 2
884 /* XXX - rename recent settings? */
885 if (recent.gui_geometry_main_upper_pane)
886 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
887 if (recent.gui_geometry_main_lower_pane)
888 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
889 if (recent.gui_geometry_status_pane)
890 gtk_paned_set_position(GTK_PANED(status_pane), recent.gui_geometry_status_pane);
896 main_save_window_geometry(GtkWidget *widget)
898 window_geometry_t geom;
900 window_get_geometry(widget, &geom);
902 if (prefs.gui_geometry_save_position) {
903 recent.gui_geometry_main_x = geom.x;
904 recent.gui_geometry_main_y = geom.y;
907 if (prefs.gui_geometry_save_size) {
908 recent.gui_geometry_main_width = geom.width,
909 recent.gui_geometry_main_height = geom.height;
912 #if GTK_MAJOR_VERSION >= 2
913 if(prefs.gui_geometry_save_maximized) {
914 recent.gui_geometry_main_maximized = geom.maximized;
917 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
918 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
919 recent.gui_geometry_status_pane = gtk_paned_get_position(GTK_PANED(status_pane));
923 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
927 /* save file first */
928 file_save_as_cmd(after_save_exit, NULL);
930 case(ESD_BTN_DONT_SAVE):
933 case(ESD_BTN_CANCEL):
936 g_assert_not_reached();
941 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
945 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
946 /* user didn't saved his current file, ask him */
947 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
948 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
949 "If you quit the program without saving, your capture data will be discarded.");
950 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
952 /* unchanged file, just exit */
958 print_usage(gboolean print_ver) {
964 fprintf(output, "This is GNU " PACKAGE " " VERSION
969 comp_info_str->str, runtime_info_str->str);
974 fprintf(output, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n",
976 fprintf(output, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
977 fprintf(output, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
978 fprintf(output, "\t[ -i <interface> ] [ -m <medium font> ] [ -N <resolving> ]\n");
979 fprintf(output, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
980 fprintf(output, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
981 fprintf(output, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
982 fprintf(output, "\t[ -w <savefile> ] [ -y <link type> ] [ -z <statistics string> ]\n");
983 fprintf(output, "\t[ <infile> ]\n");
985 fprintf(output, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
987 fprintf(output, "\t[ -N <resolving> ] [ -o <preference setting> ...\n");
988 fprintf(output, "\t[ -P <packet list height> ] [ -r <infile> ] [ -R <read filter> ]\n");
989 fprintf(output, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
990 fprintf(output, "\t[ -z <statistics string> ] [ <infile> ]\n");
1001 printf(PACKAGE " " VERSION
1006 comp_info_str->str, runtime_info_str->str);
1010 get_natural_int(const char *string, const char *name)
1015 number = strtol(string, &p, 10);
1016 if (p == string || *p != '\0') {
1017 fprintf(stderr, "ethereal: The specified %s \"%s\" isn't a decimal number\n",
1022 fprintf(stderr, "ethereal: The specified %s \"%s\" is a negative number\n",
1026 if (number > INT_MAX) {
1027 fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
1028 name, string, INT_MAX);
1035 get_positive_int(const char *string, const char *name)
1039 number = get_natural_int(string, name);
1042 fprintf(stderr, "ethereal: The specified %s is zero\n",
1052 * Given a string of the form "<autostop criterion>:<value>", as might appear
1053 * as an argument to a "-a" option, parse it and set the criterion in
1054 * question. Return an indication of whether it succeeded or failed
1058 set_autostop_criterion(const char *autostoparg)
1062 colonp = strchr(autostoparg, ':');
1070 * Skip over any white space (there probably won't be any, but
1071 * as we allow it in the preferences file, we might as well
1074 while (isspace((guchar)*p))
1078 * Put the colon back, so if our caller uses, in an
1079 * error message, the string they passed us, the message
1085 if (strcmp(autostoparg,"duration") == 0) {
1086 capture_opts.has_autostop_duration = TRUE;
1087 capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
1088 } else if (strcmp(autostoparg,"filesize") == 0) {
1089 capture_opts.has_autostop_filesize = TRUE;
1090 capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
1094 *colonp = ':'; /* put the colon back */
1099 * Given a string of the form "<ring buffer file>:<duration>", as might appear
1100 * as an argument to a "-b" option, parse it and set the arguments in
1101 * question. Return an indication of whether it succeeded or failed
1105 get_ring_arguments(const char *arg)
1107 gchar *p = NULL, *colonp;
1109 colonp = strchr(arg, ':');
1111 if (colonp != NULL) {
1116 capture_opts.ring_num_files =
1117 get_natural_int(arg, "number of ring buffer files");
1123 * Skip over any white space (there probably won't be any, but
1124 * as we allow it in the preferences file, we might as well
1127 while (isspace((guchar)*p))
1131 * Put the colon back, so if our caller uses, in an
1132 * error message, the string they passed us, the message
1139 capture_opts.has_file_duration = TRUE;
1140 capture_opts.file_duration = get_positive_int(p,
1141 "ring buffer duration");
1143 *colonp = ':'; /* put the colon back */
1148 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
1150 Once every 3 seconds we get a callback here which we use to update
1151 the tap extensions. Since Gtk1 is single threaded we dont have to
1152 worry about any locking or critical regions.
1155 update_cb(gpointer data _U_)
1157 draw_tap_listeners(FALSE);
1162 /* if these three functions are copied to gtk1 ethereal, since gtk1 does not
1163 use threads all updte_thread_mutex can be dropped and protect/unprotect
1164 would just be empty functions.
1166 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1167 gtk1-ethereal and it will just work.
1169 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1171 update_thread(gpointer data _U_)
1175 g_get_current_time(&tv1);
1176 g_static_mutex_lock(&update_thread_mutex);
1177 gdk_threads_enter();
1178 draw_tap_listeners(FALSE);
1179 gdk_threads_leave();
1180 g_static_mutex_unlock(&update_thread_mutex);
1182 g_get_current_time(&tv2);
1183 if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
1184 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1185 g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
1186 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1193 protect_thread_critical_region(void)
1195 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1196 g_static_mutex_lock(&update_thread_mutex);
1200 unprotect_thread_critical_region(void)
1202 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1203 g_static_mutex_unlock(&update_thread_mutex);
1207 /* structure to keep track of what tap listeners have been registered.
1209 typedef struct _ethereal_tap_list {
1210 struct _ethereal_tap_list *next;
1212 void (*func)(char *arg);
1213 } ethereal_tap_list;
1214 static ethereal_tap_list *tap_list=NULL;
1217 register_ethereal_tap(char *cmd, void (*func)(char *arg))
1219 ethereal_tap_list *newtl;
1221 newtl=malloc(sizeof(ethereal_tap_list));
1222 newtl->next=tap_list;
1230 enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL };
1232 /* convert drag and drop URI to a local filename */
1234 dnd_uri2filename(gchar *cf_name)
1243 * Remove URI header.
1244 * On win32 (at least WinXP), this string looks like (UNC or local filename):
1245 * file:////servername/sharename/dir1/dir2/capture-file.cap
1247 * file:///d:/dir1/dir2/capture-file.cap
1248 * we have to remove the prefix to get a valid filename.
1250 * On UNIX (at least KDE 3.0 Konqueror), this string looks like:
1251 * file:/dir1/dir2/capture-file.cap
1252 * we have to remove the file: to get a valid filename.
1254 if (strncmp("file:////", cf_name, 9) == 0) {
1255 /* win32 UNC: now becoming: //servername/sharename/dir1/dir2/capture-file.cap */
1257 } else if (strncmp("file:///", cf_name, 8) == 0) {
1258 /* win32 local: now becoming: d:/dir1/dir2/capture-file.cap */
1260 } else if (strncmp("file:", cf_name, 5) == 0) {
1261 /* unix local: now becoming: /dir1/dir2/capture-file.cap */
1266 * unescape the escaped URI characters (spaces, ...)
1268 * we have to replace escaped chars to their equivalents,
1269 * e.g. %20 (always a two digit hexstring) -> ' '
1270 * the percent character '%' is escaped be a double one "%%"
1272 * we do this conversation "in place" as the result is always
1273 * equal or smaller in size.
1281 /* this is an escaped '%' char (was: "%%") */
1286 /* convert escaped hexnumber to unscaped character */
1290 ret = sscanf(esc, "%x", &i);
1296 /* somethings wrong, just jump over that char
1297 * this will result in a wrong string, but we might get
1298 * user feedback and can fix it later ;-) */
1314 dnd_merge_files(int in_file_count, char **in_filenames)
1319 char tmpname[128+1];
1322 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1324 /* merge the files in chonological order */
1325 merge_ok = cf_merge_files(tmpname, out_fd, in_file_count, in_filenames,
1326 WTAP_FILE_PCAP, FALSE);
1330 close(out_fd); /* XXX - isn't it already closed? */
1336 /* Try to open the merged capture file. */
1337 if ((err = cf_open(tmpname, TRUE /* temporary file */, &cfile)) != 0) {
1338 /* We couldn't open it; don't dismiss the open dialog box,
1339 just leave it around so that the user can, after they
1340 dismiss the alert box popped up for the open error,
1345 switch (cf_read(&cfile)) {
1349 /* Just because we got an error, that doesn't mean we were unable
1350 to read any of the file; we handle what we could get from the
1355 /* The user bailed out of re-reading the capture file; the
1356 capture file has been closed - just free the capture file name
1357 string and return (without changing the last containing
1362 gtk_widget_grab_focus(packet_list);
1365 /* open/merge the dnd file */
1367 dnd_open_file_cmd(GtkSelectionData *selection_data)
1370 gchar *cf_name, *cf_name_freeme;
1373 GString *dialog_text;
1375 char **in_filenames;
1378 /* DND_TARGET_URL on Win32:
1379 * The selection_data->data is a single string, containing one or more URI's,
1380 * seperated by CR/NL chars. The length of the whole field can be found
1381 * in the selection_data->length field. If it contains one file, simply open it,
1382 * If it contains more than one file, ask to merge these files. */
1384 /* the data string is not zero terminated -> make a zero terminated "copy" of it */
1385 cf_name_freeme = g_malloc(selection_data->length + 1);
1386 memcpy(cf_name_freeme, selection_data->data, selection_data->length);
1387 cf_name_freeme[selection_data->length] = '\0';
1389 /* count the number of input files */
1390 cf_name = cf_name_freeme;
1391 for(in_files = 0; (cf_name = strstr(cf_name, "\r\n")) != NULL; ) {
1396 in_filenames = g_malloc(sizeof(char*) * in_files);
1398 /* store the starts of the file entries in a gchar array */
1399 cf_name = cf_name_freeme;
1400 in_filenames[0] = cf_name;
1401 for(files_work = 1; (cf_name = strstr(cf_name, "\r\n")) != NULL && files_work < in_files; ) {
1403 in_filenames[files_work] = cf_name;
1407 /* replace trailing CR NL simply with zeroes (in place), so we get valid terminated strings */
1408 cf_name = cf_name_freeme;
1409 g_strdelimit(cf_name, "\r\n", '\0');
1411 /* convert all filenames from URI to local filename (in place) */
1412 for(files_work = 0; files_work < in_files; files_work++) {
1413 in_filenames[files_work] = dnd_uri2filename(in_filenames[files_work]);
1418 /* shouldn't happen */
1421 /* open and read the capture file (this will close an existing file) */
1422 if ((err = cf_open(in_filenames[0], FALSE, &cfile)) == 0) {
1424 add_menu_recent_capture_file(in_filenames[0]);
1426 /* the capture file couldn't be read (doesn't exist, file format unknown, ...) */
1430 /* build and show the info dialog */
1431 dialog_text = g_string_sized_new(200);
1432 g_string_append(dialog_text, PRIMARY_TEXT_START
1433 "Merging the following files:" PRIMARY_TEXT_END "\n\n");
1434 for(files_work = 0; files_work < in_files; files_work++) {
1435 g_string_append(dialog_text, in_filenames[files_work]);
1436 g_string_append(dialog_text, "\n");
1438 g_string_append(dialog_text, "\nThe packets in these files will be merged chronologically into a new temporary file.");
1439 dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
1442 g_string_free(dialog_text, TRUE);
1444 /* actually merge the files now */
1445 dnd_merge_files(in_files, in_filenames);
1448 g_free(in_filenames);
1449 g_free(cf_name_freeme);
1452 /* ask the user to save current unsaved file, before opening the dnd file */
1454 dnd_save_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1458 /* save file first */
1459 file_save_as_cmd(after_save_open_dnd_file, data);
1461 case(ESD_BTN_DONT_SAVE):
1463 dnd_open_file_cmd(data);
1465 case(ESD_BTN_CANCEL):
1468 g_assert_not_reached();
1473 /* we have received some drag and drop data */
1474 /* (as we only registered to "text/uri-list", we will only get a file list here) */
1476 dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_,
1477 GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_)
1481 if (info == DND_TARGET_URL) {
1482 /* ask the user to save it's current capture file first */
1483 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1484 /* user didn't saved his current file, ask him */
1485 dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
1486 ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1487 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1488 "If you open a new capture file without saving, your current capture data will be discarded.");
1489 simple_dialog_set_cb(dialog, dnd_save_file_answered_cb, selection_data);
1491 /* unchanged file */
1492 dnd_open_file_cmd(selection_data);
1497 /* init the drag and drop functionality */
1499 dnd_init(GtkWidget *w)
1501 /* we are only interested in the URI list containing filenames */
1502 static GtkTargetEntry target_entry[] = {
1503 /*{"STRING", 0, DND_TARGET_STRING},*/
1504 /*{"text/plain", 0, DND_TARGET_STRING},*/
1505 {"text/uri-list", 0, DND_TARGET_URL}
1508 /* set this window as a dnd destination */
1510 w, GTK_DEST_DEFAULT_ALL, target_entry,
1511 sizeof(target_entry) / sizeof(GtkTargetEntry),
1512 (GdkDragAction)(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
1514 /* get notified, if some dnd coming in */
1515 gtk_signal_connect(GTK_OBJECT(w), "drag_data_received",
1516 GTK_SIGNAL_FUNC(dnd_data_received), NULL);
1520 /* And now our feature presentation... [ fade to music ] */
1522 main(int argc, char *argv[])
1530 extern char *optarg;
1531 gboolean arg_error = FALSE;
1539 char *gpf_path, *pf_path;
1540 char *cf_path, *df_path;
1541 char *gdp_path, *dp_path;
1542 int gpf_open_errno, gpf_read_errno;
1543 int pf_open_errno, pf_read_errno;
1544 int cf_open_errno, df_open_errno;
1545 int gdp_open_errno, gdp_read_errno;
1546 int dp_open_errno, dp_read_errno;
1549 gboolean start_capture = FALSE;
1550 gchar *save_file = NULL;
1553 GList *lt_list, *lt_entry;
1554 data_link_info_t *data_link_info;
1555 gchar err_str[PCAP_ERRBUF_SIZE];
1556 gchar *cant_get_if_list_errstr;
1557 gboolean stats_known;
1558 struct pcap_stat stats;
1560 gboolean capture_option_specified = FALSE;
1562 gint pl_size = 280, tv_size = 95, bv_size = 75;
1563 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1564 dfilter_t *rfcode = NULL;
1565 gboolean rfilter_parse_failed = FALSE;
1568 ethereal_tap_list *tli = NULL;
1569 gchar *tap_opt = NULL;
1570 GtkWidget *splash_win = NULL;
1572 #define OPTSTRING_INIT "a:b:B:c:f:Hhi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
1576 #define OPTSTRING_CHILD "W:Z:"
1578 #define OPTSTRING_CHILD "W:"
1581 #define OPTSTRING_CHILD ""
1582 #endif /* HAVE_LIBPCAP */
1584 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
1588 /* Set the current locale according to the program environment.
1589 * We haven't localized anything, but some GTK widgets are localized
1590 * (the file selection dialogue, for example).
1591 * This also sets the C-language locale to the native environment. */
1594 /* Let GTK get its args */
1595 gtk_init (&argc, &argv);
1597 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
1598 /* initialize our GTK eth_clist_type */
1599 init_eth_clist_type();
1602 ethereal_path = argv[0];
1605 /* Arrange that if we have no console window, and a GLib message logging
1606 routine is called to log a message, we pop up a console window.
1608 We do that by inserting our own handler for all messages logged
1609 to the default domain; that handler pops up a console if necessary,
1610 and then calls the default handler. */
1611 g_log_set_handler(NULL,
1613 G_LOG_LEVEL_CRITICAL|
1614 G_LOG_LEVEL_WARNING|
1615 G_LOG_LEVEL_MESSAGE|
1618 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION,
1619 console_log_handler, NULL);
1623 command_name = get_basename(ethereal_path);
1624 /* Set "capture_child" to indicate whether this is going to be a child
1625 process for a "-S" capture. */
1626 capture_child = (strcmp(command_name, CHILD_NAME) == 0);
1627 /* We want a splash screen only if we're not a child process */
1628 if (capture_child) {
1629 strcat(optstring, OPTSTRING_CHILD);
1633 /* We also want it only if we're not being run with "-G".
1634 XXX - we also don't want it if we're being run with
1635 "-h" or "-v", as those are options to run Ethereal and just
1636 have it print stuff to the command line. That would require
1637 that we parse the argument list before putting up the splash
1638 screen, which means we'd need to do so before reading the
1639 preference files, as that could take enough time that we'd
1640 want the splash screen up while we're doing that. Unfortunately,
1641 that means we'd have to queue up, for example, "-o" options,
1642 so that we apply them *after* reading the preferences, as
1643 they're supposed to override saved preferences. */
1644 if (argc < 2 || strcmp(argv[1], "-G") != 0) {
1645 splash_win = splash_new("Loading Ethereal ...");
1649 splash_update(splash_win, "Registering dissectors ...");
1651 /* Register all dissectors; we must do this before checking for the
1652 "-G" flag, as the "-G" flag dumps information registered by the
1653 dissectors, and we must do it before we read the preferences, in
1654 case any dissectors register preferences. */
1655 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
1656 failure_alert_box,open_failure_alert_box,read_failure_alert_box);
1658 splash_update(splash_win, "Registering tap listeners ...");
1660 /* Register all tap listeners; we do this before we parse the arguments,
1661 as the "-z" argument can specify a registered tap. */
1662 register_all_tap_listeners();
1664 splash_update(splash_win, "Loading module preferences ...");
1666 /* Now register the preferences for any non-dissector modules.
1667 We must do that before we read the preferences as well. */
1668 prefs_register_modules();
1670 /* If invoked with the "-G" flag, we dump out information based on
1671 the argument to the "-G" flag; if no argument is specified,
1672 for backwards compatibility we dump out a glossary of display
1675 We must do this before calling "gtk_init()", because "gtk_init()"
1676 tries to open an X display, and we don't want to have to do any X
1677 stuff just to do a build.
1679 Given that we call "gtk_init()" before doing the regular argument
1680 list processing, so that it can handle X and GTK+ arguments and
1681 remove them from the list at which we look, this means we must do
1682 this before doing the regular argument list processing, as well.
1686 you must give the "-G" flag as the first flag on the command line;
1688 you must give it as "-G", nothing more, nothing less;
1690 the first argument after the "-G" flag, if present, will be used
1691 to specify the information to dump;
1693 arguments after that will not be used. */
1694 handle_dashG_option(argc, argv, "ethereal");
1696 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
1697 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
1700 g_thread_init(NULL);
1702 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
1703 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
1705 #else /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
1706 /* this is to keep tap extensions updating once every 3 seconds */
1707 gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
1708 #endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
1711 gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
1714 splash_update(splash_win, "Loading configuration files ...");
1716 /* Read the preference files. */
1717 prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1718 &pf_open_errno, &pf_read_errno, &pf_path);
1719 if (gpf_path != NULL) {
1720 if (gpf_open_errno != 0) {
1721 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1722 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1723 strerror(gpf_open_errno));
1725 if (gpf_read_errno != 0) {
1726 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1727 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1728 strerror(gpf_read_errno));
1731 if (pf_path != NULL) {
1732 if (pf_open_errno != 0) {
1733 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1734 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1735 strerror(pf_open_errno));
1737 if (pf_read_errno != 0) {
1738 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1739 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1740 strerror(pf_read_errno));
1747 if (prefs->gui_console_open == console_open_always) {
1753 capture_opts.has_snaplen = FALSE;
1754 capture_opts.snaplen = MIN_PACKET_SIZE;
1755 capture_opts.linktype = -1;
1757 capture_opts.buffer_size = 1;
1759 capture_opts.quit_after_cap = FALSE;
1761 capture_opts.has_autostop_packets = FALSE;
1762 capture_opts.autostop_packets = 1;
1763 capture_opts.has_autostop_duration = FALSE;
1764 capture_opts.autostop_duration = 60 /* 1 min */;
1765 capture_opts.has_autostop_filesize = FALSE;
1766 capture_opts.autostop_filesize = 1024 * 1024 /* 1 MB */;
1767 capture_opts.has_autostop_files = FALSE;
1768 capture_opts.autostop_files = 1;
1770 capture_opts.multi_files_on = FALSE;
1771 capture_opts.has_ring_num_files = TRUE;
1772 capture_opts.ring_num_files = 2;
1773 capture_opts.has_file_duration = FALSE;
1774 capture_opts.file_duration = 60 /* 1 min */;
1776 /* If this is a capture child process, it should pay no attention
1777 to the "prefs.capture_prom_mode" setting in the preferences file;
1778 it should do what the parent process tells it to do, and if
1779 the parent process wants it not to run in promiscuous mode, it'll
1780 tell it so with a "-p" flag.
1782 Otherwise, set promiscuous mode from the preferences setting. */
1783 /* the same applies to other preferences settings as well. */
1784 if (capture_child) {
1785 capture_opts.promisc_mode = TRUE; /* maybe changed by command line below */
1786 capture_opts.show_info = TRUE; /* maybe changed by command line below */
1787 capture_opts.sync_mode = TRUE; /* always true in child process */
1788 auto_scroll_live = FALSE; /* doesn't matter in child process */
1791 capture_opts.promisc_mode = prefs->capture_prom_mode;
1792 capture_opts.show_info = prefs->capture_show_info;
1793 capture_opts.sync_mode = prefs->capture_real_time;
1794 auto_scroll_live = prefs->capture_auto_scroll;
1797 #endif /* HAVE_LIBPCAP */
1799 /* Set the name resolution code's flags from the preferences. */
1800 g_resolv_flags = prefs->name_resolve;
1802 /* Read the capture filter file. */
1803 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1804 if (cf_path != NULL) {
1805 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1806 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1807 strerror(cf_open_errno));
1811 /* Read the display filter file. */
1812 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1813 if (df_path != NULL) {
1814 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1815 "Could not open your display filter file\n\"%s\": %s.", df_path,
1816 strerror(df_open_errno));
1820 /* Read the disabled protocols file. */
1821 read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
1822 &dp_path, &dp_open_errno, &dp_read_errno);
1823 if (gdp_path != NULL) {
1824 if (gdp_open_errno != 0) {
1825 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1826 "Could not open global disabled protocols file\n\"%s\": %s.",
1827 gdp_path, strerror(gdp_open_errno));
1829 if (gdp_read_errno != 0) {
1830 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1831 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1832 gdp_path, strerror(gdp_read_errno));
1836 if (dp_path != NULL) {
1837 if (dp_open_errno != 0) {
1838 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1839 "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
1840 strerror(dp_open_errno));
1842 if (dp_read_errno != 0) {
1843 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1844 "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
1845 strerror(dp_read_errno));
1850 init_cap_file(&cfile);
1853 /* Load wpcap if possible. Do this before collecting the run-time version information */
1856 /* Start windows sockets */
1857 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1860 /* Assemble the compile-time version information string */
1861 comp_info_str = g_string_new("Compiled ");
1862 g_string_append(comp_info_str, "with ");
1863 g_string_sprintfa(comp_info_str,
1864 #ifdef GTK_MAJOR_VERSION
1865 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1868 "GTK+ (version unknown)");
1871 g_string_append(comp_info_str, ", ");
1872 get_compiled_version_info(comp_info_str);
1874 /* Assemble the run-time version information string */
1875 runtime_info_str = g_string_new("Running ");
1876 get_runtime_version_info(runtime_info_str);
1878 /* Now get our args */
1879 while ((opt = getopt(argc, argv, optstring)) != -1) {
1881 case 'a': /* autostop criteria */
1883 if (set_autostop_criterion(optarg) == FALSE) {
1884 fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
1888 capture_option_specified = TRUE;
1892 case 'b': /* Ringbuffer option */
1894 capture_opts.multi_files_on = TRUE;
1895 capture_opts.has_ring_num_files = TRUE;
1896 if (get_ring_arguments(optarg) == FALSE) {
1897 fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
1901 capture_option_specified = TRUE;
1905 case 'B': /* Byte view pane height */
1906 bv_size = get_positive_int(optarg, "byte view pane height");
1908 case 'c': /* Capture xxx packets */
1910 capture_opts.has_autostop_packets = TRUE;
1911 capture_opts.autostop_packets = get_positive_int(optarg, "packet count");
1913 capture_option_specified = TRUE;
1920 g_free(cfile.cfilter);
1921 cfile.cfilter = g_strdup(optarg);
1923 capture_option_specified = TRUE;
1927 case 'h': /* Print help and exit */
1931 case 'i': /* Use interface xxx */
1933 cfile.iface = g_strdup(optarg);
1935 capture_option_specified = TRUE;
1939 case 'k': /* Start capture immediately */
1941 start_capture = TRUE;
1943 capture_option_specified = TRUE;
1947 case 'l': /* Automatic scrolling in live capture mode */
1949 auto_scroll_live = TRUE;
1951 capture_option_specified = TRUE;
1955 case 'H': /* Hide capture info dialog box */
1957 capture_opts.show_info = FALSE;
1959 capture_option_specified = TRUE;
1963 case 'L': /* Print list of link-layer types and exit */
1965 list_link_layer_types = TRUE;
1967 capture_option_specified = TRUE;
1971 case 'm': /* Fixed-width font for the display */
1972 if (prefs->PREFS_GUI_FONT_NAME != NULL)
1973 g_free(prefs->PREFS_GUI_FONT_NAME);
1974 prefs->PREFS_GUI_FONT_NAME = g_strdup(optarg);
1976 case 'n': /* No name resolution */
1977 g_resolv_flags = RESOLV_NONE;
1979 case 'N': /* Select what types of addresses/port #s to resolve */
1980 if (g_resolv_flags == RESOLV_ALL)
1981 g_resolv_flags = RESOLV_NONE;
1982 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
1983 if (badopt != '\0') {
1984 fprintf(stderr, "ethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
1989 case 'o': /* Override preference from command line */
1990 switch (prefs_set_pref(optarg)) {
1992 case PREFS_SET_SYNTAX_ERR:
1993 fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
1997 case PREFS_SET_NO_SUCH_PREF:
1998 case PREFS_SET_OBSOLETE:
1999 fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
2005 case 'p': /* Don't capture in promiscuous mode */
2007 capture_opts.promisc_mode = FALSE;
2009 capture_option_specified = TRUE;
2013 case 'P': /* Packet list pane height */
2014 pl_size = get_positive_int(optarg, "packet list pane height");
2016 case 'Q': /* Quit after capture (just capture to file) */
2018 capture_opts.quit_after_cap = TRUE;
2019 start_capture = TRUE; /*** -Q implies -k !! ***/
2021 capture_option_specified = TRUE;
2025 case 'r': /* Read capture file xxx */
2026 /* We may set "last_open_dir" to "cf_name", and if we change
2027 "last_open_dir" later, we free the old value, so we have to
2028 set "cf_name" to something that's been allocated. */
2029 cf_name = g_strdup(optarg);
2031 case 'R': /* Read file filter */
2034 case 's': /* Set the snapshot (capture) length */
2036 capture_opts.has_snaplen = TRUE;
2037 capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
2039 capture_option_specified = TRUE;
2043 case 'S': /* "Sync" mode: used for following file ala tail -f */
2045 capture_opts.sync_mode = TRUE;
2047 capture_option_specified = TRUE;
2051 case 't': /* Time stamp type */
2052 if (strcmp(optarg, "r") == 0)
2053 set_timestamp_setting(TS_RELATIVE);
2054 else if (strcmp(optarg, "a") == 0)
2055 set_timestamp_setting(TS_ABSOLUTE);
2056 else if (strcmp(optarg, "ad") == 0)
2057 set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
2058 else if (strcmp(optarg, "d") == 0)
2059 set_timestamp_setting(TS_DELTA);
2061 fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
2063 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
2064 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
2068 case 'T': /* Tree view pane height */
2069 tv_size = get_positive_int(optarg, "tree view pane height");
2071 case 'v': /* Show version and exit */
2078 case 'w': /* Write to capture file xxx */
2080 save_file = g_strdup(optarg);
2082 capture_option_specified = TRUE;
2086 case 'y': /* Set the pcap data link type */
2088 #ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
2089 capture_opts.linktype = pcap_datalink_name_to_val(optarg);
2090 if (capture_opts.linktype == -1) {
2091 fprintf(stderr, "ethereal: The specified data link type \"%s\" isn't valid\n",
2095 #else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
2096 /* XXX - just treat it as a number */
2097 capture_opts.linktype = get_natural_int(optarg, "data link type");
2098 #endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
2099 #else /* HAVE_LIBPCAP */
2100 capture_option_specified = TRUE;
2102 #endif /* HAVE_LIBPCAP */
2105 /* This is a hidden option supporting Sync mode, so we don't set
2106 * the error flags for the user in the non-libpcap case.
2108 case 'W': /* Write to capture file FD xxx */
2109 cfile.save_file_fd = atoi(optarg);
2113 for(tli=tap_list;tli;tli=tli->next){
2114 if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
2115 tap_opt = g_strdup(optarg);
2120 fprintf(stderr,"ethereal: invalid -z argument.\n");
2121 fprintf(stderr," -z argument must be one of :\n");
2122 for(tli=tap_list;tli;tli=tli->next){
2123 fprintf(stderr," %s\n",tli->cmd);
2131 /* Hidden option supporting Sync mode */
2132 case 'Z': /* Write to pipe FD XXX */
2133 /* associate stdout with pipe */
2135 if (dup2(i, 1) < 0) {
2136 fprintf(stderr, "Unable to dup pipe handle\n");
2140 #endif /* HAVE_LIBPCAP */
2144 case '?': /* Bad flag - print usage message */
2152 if (cf_name != NULL) {
2154 * Input file name specified with "-r" *and* specified as a regular
2155 * command-line argument.
2160 * Input file name not specified with "-r", and a command-line argument
2161 * was specified; treat it as the input file name.
2163 * Yes, this is different from tethereal, where non-flag command-line
2164 * arguments are a filter, but this works better on GUI desktops
2165 * where a command can be specified to be run to open a particular
2166 * file - yes, you could have "-r" as the last part of the command,
2167 * but that's a bit ugly.
2169 cf_name = g_strdup(argv[0]);
2177 * Extra command line arguments were specified; complain.
2179 fprintf(stderr, "Invalid argument: %s\n", argv[0]);
2183 #ifndef HAVE_LIBPCAP
2184 if (capture_option_specified)
2185 fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
2193 if (start_capture && list_link_layer_types) {
2194 /* Specifying *both* is bogus. */
2195 fprintf(stderr, "ethereal: You can't specify both -L and a live capture.\n");
2199 if (list_link_layer_types) {
2200 /* We're supposed to list the link-layer types for an interface;
2201 did the user also specify a capture file to be read? */
2203 /* Yes - that's bogus. */
2204 fprintf(stderr, "ethereal: You can't specify -L and a capture file to be read.\n");
2207 /* No - did they specify a ring buffer option? */
2208 if (capture_opts.multi_files_on) {
2209 fprintf(stderr, "ethereal: Ring buffer requested, but a capture isn't being done.\n");
2213 /* We're supposed to do a live capture; did the user also specify
2214 a capture file to be read? */
2215 if (start_capture && cf_name) {
2216 /* Yes - that's bogus. */
2217 fprintf(stderr, "ethereal: You can't specify both a live capture and a capture file to be read.\n");
2221 /* No - was the ring buffer option specified and, if so, does it make
2223 if (capture_opts.multi_files_on) {
2224 /* Ring buffer works only under certain conditions:
2225 a) ring buffer does not work with temporary files;
2226 b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive -
2227 sync_mode takes precedence;
2228 c) it makes no sense to enable the ring buffer if the maximum
2229 file size is set to "infinite". */
2230 if (save_file == NULL) {
2231 fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
2232 capture_opts.multi_files_on = FALSE;
2234 if (capture_opts.sync_mode) {
2235 fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
2236 capture_opts.multi_files_on = FALSE;
2238 if (!capture_opts.has_autostop_filesize) {
2239 fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
2240 capture_opts.multi_files_on = FALSE;
2245 if (start_capture || list_link_layer_types) {
2246 /* Did the user specify an interface to use? */
2247 if (cfile.iface == NULL) {
2248 /* No - is a default specified in the preferences file? */
2249 if (prefs->capture_device != NULL) {
2251 cfile.iface = g_strdup(prefs->capture_device);
2253 /* No - pick the first one from the list of interfaces. */
2254 if_list = get_interface_list(&err, err_str);
2255 if (if_list == NULL) {
2258 case CANT_GET_INTERFACE_LIST:
2259 cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
2260 fprintf(stderr, "%s\n", cant_get_if_list_errstr);
2261 g_free(cant_get_if_list_errstr);
2264 case NO_INTERFACES_FOUND:
2265 fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
2270 if_info = if_list->data; /* first interface */
2271 cfile.iface = g_strdup(if_info->name);
2272 free_interface_list(if_list);
2277 if (capture_child) {
2278 if (cfile.save_file_fd == -1) {
2279 /* XXX - send this to the standard output as something our parent
2280 should put in an error message box? */
2281 fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
2286 if (list_link_layer_types) {
2287 /* Get the list of link-layer types for the capture device. */
2288 lt_list = get_pcap_linktype_list(cfile.iface, err_str);
2289 if (lt_list == NULL) {
2290 if (err_str[0] != '\0') {
2291 fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n"
2292 "Please check to make sure you have sufficient permissions, and that\n"
2293 "you have the proper interface or pipe specified.\n", err_str);
2295 fprintf(stderr, "ethereal: The capture device has no data link types.\n");
2298 fprintf(stderr, "Data link types (use option -y to set):\n");
2299 for (lt_entry = lt_list; lt_entry != NULL;
2300 lt_entry = g_list_next(lt_entry)) {
2301 data_link_info = lt_entry->data;
2302 fprintf(stderr, " %s", data_link_info->name);
2303 if (data_link_info->description != NULL)
2304 fprintf(stderr, " (%s)", data_link_info->description);
2306 fprintf(stderr, " (not supported)");
2309 free_pcap_linktype_list(lt_list);
2315 /* Notify all registered modules that have had any of their preferences
2316 changed either from one of the preferences file or from the command
2317 line that their preferences have changed. */
2320 /* disabled protocols as per configuration file */
2321 if (gdp_path == NULL && dp_path == NULL) {
2322 set_disabled_protos_list();
2325 /* Build the column format array */
2326 col_setup(&cfile.cinfo, prefs->num_cols);
2327 for (i = 0; i < cfile.cinfo.num_cols; i++) {
2328 cfile.cinfo.col_fmt[i] = get_column_format(i);
2329 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
2330 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
2332 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
2333 cfile.cinfo.col_data[i] = NULL;
2334 if (cfile.cinfo.col_fmt[i] == COL_INFO)
2335 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
2337 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2338 cfile.cinfo.col_fence[i] = 0;
2339 cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2340 cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2343 for (i = 0; i < cfile.cinfo.num_cols; i++) {
2346 for (j = 0; j < NUM_COL_FMTS; j++) {
2347 if (!cfile.cinfo.fmt_matx[i][j])
2350 if (cfile.cinfo.col_first[j] == -1)
2351 cfile.cinfo.col_first[j] = i;
2352 cfile.cinfo.col_last[j] = i;
2357 if (capture_opts.has_snaplen) {
2358 if (capture_opts.snaplen < 1)
2359 capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
2360 else if (capture_opts.snaplen < MIN_PACKET_SIZE)
2361 capture_opts.snaplen = MIN_PACKET_SIZE;
2364 /* Check the value range of the ringbuffer_num_files parameter */
2365 if (capture_opts.ring_num_files > RINGBUFFER_MAX_NUM_FILES)
2366 capture_opts.ring_num_files = RINGBUFFER_MAX_NUM_FILES;
2367 #if RINGBUFFER_MIN_NUM_FILES > 0
2368 else if (capture_opts.num_files < RINGBUFFER_MIN_NUM_FILES)
2369 capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
2373 /* read in rc file from global and personal configuration paths. */
2374 /* XXX - is this a good idea? */
2375 gtk_rc_parse(RC_FILE);
2376 rc_file = get_persconffile_path(RC_FILE, FALSE);
2377 gtk_rc_parse(rc_file);
2381 /* close the splash screen, as we are going to open the main window now */
2382 splash_destroy(splash_win);
2385 /* Is this a "child" ethereal, which is only supposed to pop up a
2386 capture box to let us stop the capture, and run a capture
2387 to a file that our parent will read? */
2388 if (!capture_child) {
2390 /* No. Pop up the main window, and read in a capture file if
2392 create_main_window(pl_size, tv_size, bv_size, prefs);
2394 /* Read the recent file, as we have the gui now ready for it. */
2395 read_recent(&rf_path, &rf_open_errno);
2397 /* rearrange all the widgets as we now have the recent settings for this */
2398 main_widgets_rearrange();
2400 /* Fill in column titles. This must be done after the top level window
2403 XXX - is that still true, with fixed-width columns? */
2404 packet_list_set_column_titles();
2406 menu_recent_read_finished();
2408 switch (user_font_apply()) {
2411 case FA_FONT_NOT_RESIZEABLE:
2412 /* "user_font_apply()" popped up an alert box. */
2413 /* turn off zooming - font can't be resized */
2414 case FA_FONT_NOT_AVAILABLE:
2415 /* XXX - did we successfully load the un-zoomed version earlier?
2416 If so, this *probably* means the font is available, but not at
2417 this particular zoom level, but perhaps some other failure
2418 occurred; I'm not sure you can determine which is the case,
2420 /* turn off zooming - zoom level is unavailable */
2422 /* in any other case than FA_SUCCESS, turn off zooming */
2423 recent.gui_zoom_level = 0;
2424 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2427 dnd_init(top_level);
2433 /* the window can be sized only, if it's not already shown, so do it now! */
2434 main_load_window_geometry(top_level);
2436 /*** we have finished all init things, show the main window ***/
2437 gtk_widget_show(top_level);
2439 /* the window can be maximized only, if it's visible, so do it after show! */
2440 main_load_window_geometry(top_level);
2442 /* process all pending GUI events before continue */
2443 while (gtk_events_pending()) gtk_main_iteration();
2445 /* Pop up any queued-up alert boxes. */
2446 display_queued_messages();
2448 /* If we were given the name of a capture file, read it in now;
2449 we defer it until now, so that, if we can't open it, and pop
2450 up an alert box, the alert box is more likely to come up on
2451 top of the main window - but before the preference-file-error
2452 alert box, so, if we get one of those, it's more likely to come
2455 if (rfilter != NULL) {
2456 if (!dfilter_compile(rfilter, &rfcode)) {
2457 bad_dfilter_alert_box(rfilter);
2458 rfilter_parse_failed = TRUE;
2461 if (!rfilter_parse_failed) {
2462 if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
2463 /* "cf_open()" succeeded, so it closed the previous
2464 capture file, and thus destroyed any previous read filter
2465 attached to "cf". */
2466 cfile.rfcode = rfcode;
2468 /* Open tap windows; we do so after creating the main window,
2469 to avoid GTK warnings, and after successfully opening the
2470 capture file, so we know we have something to tap. */
2471 if (tap_opt && tli) {
2472 (*tli->func)(tap_opt);
2476 /* Read the capture file. */
2477 switch (cf_read(&cfile)) {
2481 /* Just because we got an error, that doesn't mean we were unable
2482 to read any of the file; we handle what we could get from the
2491 /* Save the name of the containing directory specified in the
2492 path name, if any; we can write over cf_name, which is a
2493 good thing, given that "get_dirname()" does write over its
2495 s = get_dirname(cf_name);
2496 /* we might already set this from the recent file, don't overwrite this */
2497 if(get_last_open_dir() == NULL)
2498 set_last_open_dir(s);
2503 dfilter_free(rfcode);
2504 cfile.rfcode = NULL;
2509 if (start_capture) {
2510 /* "-k" was specified; start a capture. */
2511 if (do_capture(save_file)) {
2512 /* The capture started. Open tap windows; we do so after creating
2513 the main window, to avoid GTK warnings, and after starting the
2514 capture, so we know we have something to tap. */
2515 if (tap_opt && tli) {
2516 (*tli->func)(tap_opt);
2520 if (save_file != NULL) {
2521 /* Save the directory name for future file dialogs. */
2522 s = get_dirname(save_file); /* Overwrites save_file */
2523 set_last_open_dir(s);
2529 set_menus_for_capture_in_progress(FALSE);
2532 /* This is the child process for a sync mode or fork mode capture,
2533 so just do the low-level work of a capture - don't create
2534 a temporary file and fork off *another* child process (so don't
2535 call "do_capture()"). */
2537 /* Pop up any queued-up alert boxes. */
2538 display_queued_messages();
2540 /* XXX - hand these stats to the parent process */
2541 capture_start(&stats_known, &stats);
2543 /* The capture is done; there's nothing more for us to do. */
2546 if (!start_capture && (cfile.cfilter == NULL || strlen(cfile.cfilter) == 0)) {
2547 if (cfile.cfilter) {
2548 g_free(cfile.cfilter);
2550 cfile.cfilter = g_strdup(get_conn_cfilter());
2552 #else /* HAVE_LIBPCAP */
2553 set_menus_for_capture_in_progress(FALSE);
2554 #endif /* HAVE_LIBPCAP */
2562 /* Shutdown windows sockets */
2565 /* For some unknown reason, the "atexit()" call in "create_console()"
2566 doesn't arrange that "destroy_console()" be called when we exit,
2567 so we call it here if a console was created. */
2573 /* This isn't reached, but we need it to keep GCC from complaining
2574 that "main()" returns without returning a value - it knows that
2575 "exit()" never returns, but it doesn't know that "gtk_exit()"
2576 doesn't, as GTK+ doesn't declare it with the attribute
2578 return 0; /* not reached */
2583 /* We build this as a GUI subsystem application on Win32, so
2584 "WinMain()", not "main()", gets called.
2586 Hack shamelessly stolen from the Win32 port of the GIMP. */
2588 #define _stdcall __attribute__((stdcall))
2592 WinMain (struct HINSTANCE__ *hInstance,
2593 struct HINSTANCE__ *hPrevInstance,
2597 has_console = FALSE;
2598 return main (__argc, __argv);
2602 * If this application has no console window to which its standard output
2603 * would go, create one.
2606 create_console(void)
2608 if (!has_console && prefs.gui_console_open != console_open_never) {
2609 /* We have no console to which to print the version string, so
2610 create one and make it the standard input, output, and error. */
2611 if (!AllocConsole())
2612 return; /* couldn't create console */
2613 freopen("CONIN$", "r", stdin);
2614 freopen("CONOUT$", "w", stdout);
2615 freopen("CONOUT$", "w", stderr);
2617 /* Well, we have a console now. */
2620 /* Now register "destroy_console()" as a routine to be called just
2621 before the application exits, so that we can destroy the console
2622 after the user has typed a key (so that the console doesn't just
2623 disappear out from under them, giving the user no chance to see
2624 the message(s) we put in there). */
2625 atexit(destroy_console);
2630 destroy_console(void)
2633 printf("\n\nPress any key to exit\n");
2639 /* This routine should not be necessary, at least as I read the GLib
2640 source code, as it looks as if GLib is, on Win32, *supposed* to
2641 create a console window into which to display its output.
2643 That doesn't happen, however. I suspect there's something completely
2644 broken about that code in GLib-for-Win32, and that it may be related
2645 to the breakage that forces us to just call "printf()" on the message
2646 rather than passing the message on to "g_log_default_handler()"
2647 (which is the routine that does the aforementioned non-functional
2648 console window creation). */
2650 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2651 const char *message, gpointer user_data)
2655 /* For some unknown reason, the above doesn't appear to actually cause
2656 anything to be sent to the standard output, so we'll just splat the
2657 message out directly, just to make sure it gets out. */
2658 printf("%s\n", message);
2660 g_log_default_handler(log_domain, log_level, message, user_data);
2665 GtkWidget *info_bar_new(void)
2667 /* tip: tooltips don't work on statusbars! */
2668 info_bar = gtk_statusbar_new();
2669 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
2670 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
2671 help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
2672 #if GTK_MAJOR_VERSION >= 2
2673 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
2675 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
2680 GtkWidget *packets_bar_new(void)
2682 /* tip: tooltips don't work on statusbars! */
2683 packets_bar = gtk_statusbar_new();
2684 packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
2685 packets_bar_update();
2692 * Helper for main_widgets_rearrange()
2694 void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
2695 gtk_container_remove(GTK_CONTAINER(data), widget);
2698 GtkWidget *main_widget_layout(gint layout_content)
2700 switch(layout_content) {
2701 case(layout_pane_content_none):
2704 case(layout_pane_content_plist):
2707 case(layout_pane_content_pdetails):
2710 case(layout_pane_content_pbytes):
2714 g_assert_not_reached();
2721 * Rearrange the main window widgets
2723 void main_widgets_rearrange(void) {
2724 GtkWidget *first_pane_widget1, *first_pane_widget2;
2725 GtkWidget *second_pane_widget1, *second_pane_widget2;
2726 gboolean split_top_left;
2728 /* be a bit faster */
2729 gtk_widget_hide(main_vbox);
2731 /* be sure, we don't loose a widget while rearranging */
2732 gtk_widget_ref(menubar);
2733 gtk_widget_ref(main_tb);
2734 gtk_widget_ref(filter_tb);
2735 gtk_widget_ref(pkt_scrollw);
2736 gtk_widget_ref(tv_scrollw);
2737 gtk_widget_ref(byte_nb_ptr);
2738 gtk_widget_ref(stat_hbox);
2739 gtk_widget_ref(info_bar);
2740 gtk_widget_ref(packets_bar);
2741 gtk_widget_ref(status_pane);
2742 gtk_widget_ref(main_pane_v1);
2743 gtk_widget_ref(main_pane_v2);
2744 gtk_widget_ref(main_pane_h1);
2745 gtk_widget_ref(main_pane_h2);
2747 /* empty all containers participating */
2748 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
2749 gtk_container_foreach(GTK_CONTAINER(stat_hbox), foreach_remove_a_child, stat_hbox);
2750 gtk_container_foreach(GTK_CONTAINER(status_pane), foreach_remove_a_child, status_pane);
2751 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
2752 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
2753 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
2754 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
2756 /* add the menubar always at the top */
2757 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
2760 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
2762 /* filter toolbar in toolbar area */
2763 if (!prefs.filter_toolbar_show_in_statusbar) {
2764 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
2767 /* fill the main layout panes */
2768 switch(prefs.gui_layout_type) {
2769 case(layout_type_5):
2770 main_first_pane = main_pane_v1;
2771 main_second_pane = main_pane_v2;
2772 split_top_left = FALSE;
2774 case(layout_type_2):
2775 main_first_pane = main_pane_v1;
2776 main_second_pane = main_pane_h1;
2777 split_top_left = FALSE;
2779 case(layout_type_1):
2780 main_first_pane = main_pane_v1;
2781 main_second_pane = main_pane_h1;
2782 split_top_left = TRUE;
2784 case(layout_type_4):
2785 main_first_pane = main_pane_h1;
2786 main_second_pane = main_pane_v1;
2787 split_top_left = FALSE;
2789 case(layout_type_3):
2790 main_first_pane = main_pane_h1;
2791 main_second_pane = main_pane_v1;
2792 split_top_left = TRUE;
2794 case(layout_type_6):
2795 main_first_pane = main_pane_h1;
2796 main_second_pane = main_pane_h2;
2797 split_top_left = FALSE;
2800 main_first_pane = NULL;
2801 main_second_pane = NULL;
2802 split_top_left = FALSE;
2803 g_assert_not_reached();
2805 if (split_top_left) {
2806 first_pane_widget1 = main_second_pane;
2807 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2808 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
2809 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2811 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2812 first_pane_widget2 = main_second_pane;
2813 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
2814 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2816 if (first_pane_widget1 != NULL)
2817 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
2818 if (first_pane_widget2 != NULL)
2819 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
2820 if (second_pane_widget1 != NULL)
2821 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
2822 if (second_pane_widget2 != NULL)
2823 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
2825 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
2827 /* statusbar hbox */
2828 gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
2830 /* filter toolbar in statusbar hbox */
2831 if (prefs.filter_toolbar_show_in_statusbar) {
2832 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
2836 gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
2837 gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
2838 gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
2840 /* hide widgets on users recent settings */
2841 main_widgets_show_or_hide();
2843 gtk_widget_show(main_vbox);
2847 is_widget_visible(GtkWidget *widget, gpointer data)
2849 gboolean *is_visible = data;
2852 if (GTK_WIDGET_VISIBLE(widget))
2858 * XXX - this doesn't appear to work with the paned widgets in
2859 * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
2860 * and the other pane doesn't grow to take up the rest of the pane.
2861 * It does appear to work with GTK+ 2.x.
2864 main_widgets_show_or_hide(void)
2866 gboolean main_second_pane_show;
2868 if (recent.main_toolbar_show) {
2869 gtk_widget_show(main_tb);
2871 gtk_widget_hide(main_tb);
2875 * Show the status hbox if either:
2877 * 1) we're showing the filter toolbar and we want it in the status
2882 * 2) we're showing the status bar.
2884 if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
2885 recent.statusbar_show) {
2886 gtk_widget_show(stat_hbox);
2888 gtk_widget_hide(stat_hbox);
2891 if (recent.statusbar_show) {
2892 gtk_widget_show(status_pane);
2894 gtk_widget_hide(status_pane);
2897 if (recent.filter_toolbar_show) {
2898 gtk_widget_show(filter_tb);
2900 gtk_widget_hide(filter_tb);
2903 if (recent.packet_list_show) {
2904 gtk_widget_show(pkt_scrollw);
2906 gtk_widget_hide(pkt_scrollw);
2909 if (recent.tree_view_show) {
2910 gtk_widget_show(tv_scrollw);
2912 gtk_widget_hide(tv_scrollw);
2915 if (recent.byte_view_show) {
2916 gtk_widget_show(byte_nb_ptr);
2918 gtk_widget_hide(byte_nb_ptr);
2922 * Is anything in "main_second_pane" visible?
2923 * If so, show it, otherwise hide it.
2925 main_second_pane_show = FALSE;
2926 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
2927 &main_second_pane_show);
2928 if (main_second_pane_show) {
2929 gtk_widget_show(main_second_pane);
2931 gtk_widget_hide(main_second_pane);
2936 #if GTK_MAJOR_VERSION >= 2
2937 /* called, when the window state changes (minimized, maximized, ...) */
2939 window_state_event_cb (GtkWidget *widget _U_,
2943 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
2945 if( (event->type) == (GDK_WINDOW_STATE)) {
2946 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
2947 /* we might have dialogs popped up while we where iconified,
2949 display_queued_messages();
2958 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
2961 *filter_bt, *filter_cm, *filter_te,
2962 *filter_add_expr_bt,
2965 GList *filter_list = NULL;
2966 GtkTooltips *tooltips;
2967 GtkAccelGroup *accel;
2969 /* Display filter construct dialog has an Apply button, and "OK" not
2970 only sets our text widget, it activates it (i.e., it causes us to
2971 filter the capture). */
2972 static construct_args_t args = {
2973 "Ethereal: Display Filter",
2978 /* use user-defined title if preference is set */
2979 title = create_user_window_title("The Ethereal Network Analyzer");
2982 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
2985 tooltips = gtk_tooltips_new();
2988 #if GTK_MAJOR_VERSION < 2
2989 /* has to be done, after top_level window is created */
2990 app_font_gtk1_init(top_level);
2994 gtk_widget_set_name(top_level, "main window");
2995 SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
2997 #if GTK_MAJOR_VERSION >= 2
2998 SIGNAL_CONNECT(GTK_OBJECT(top_level), "window_state_event",
2999 G_CALLBACK (window_state_event_cb), NULL);
3002 gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
3004 /* Container for menu bar, toolbar(s), paned windows and progress/info box */
3005 main_vbox = gtk_vbox_new(FALSE, 1);
3006 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
3007 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3008 gtk_widget_show(main_vbox);
3011 menubar = main_menu_new(&accel);
3012 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3013 gtk_widget_show(menubar);
3016 main_tb = toolbar_new();
3017 gtk_widget_show (main_tb);
3020 pkt_scrollw = packet_list_new(prefs);
3021 WIDGET_SET_SIZE(packet_list, -1, pl_size);
3022 gtk_widget_show(pkt_scrollw);
3025 tv_scrollw = main_tree_view_new(prefs, &tree_view);
3026 WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
3027 gtk_widget_show(tv_scrollw);
3029 #if GTK_MAJOR_VERSION < 2
3030 SIGNAL_CONNECT(tree_view, "tree-select-row", tree_view_select_row_cb, NULL);
3031 SIGNAL_CONNECT(tree_view, "tree-unselect-row", tree_view_unselect_row_cb,
3034 SIGNAL_CONNECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
3035 "changed", tree_view_selection_changed_cb, NULL);
3037 SIGNAL_CONNECT(tree_view, "button_press_event", popup_menu_handler,
3038 OBJECT_GET_DATA(popup_menu_object, PM_TREE_VIEW_KEY));
3039 gtk_widget_show(tree_view);
3042 byte_nb_ptr = byte_view_new();
3043 WIDGET_SET_SIZE(byte_nb_ptr, -1, bv_size);
3044 gtk_widget_show(byte_nb_ptr);
3046 SIGNAL_CONNECT(byte_nb_ptr, "button_press_event", popup_menu_handler,
3047 OBJECT_GET_DATA(popup_menu_object, PM_HEXDUMP_KEY));
3050 /* Panes for the packet list, tree, and byte view */
3051 main_pane_v1 = gtk_vpaned_new();
3052 gtk_widget_show(main_pane_v1);
3053 main_pane_v2 = gtk_vpaned_new();
3054 gtk_widget_show(main_pane_v2);
3055 main_pane_h1 = gtk_hpaned_new();
3056 gtk_widget_show(main_pane_h1);
3057 main_pane_h2 = gtk_hpaned_new();
3058 gtk_widget_show(main_pane_h2);
3060 /* filter toolbar */
3061 #if GTK_MAJOR_VERSION < 2
3062 filter_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
3065 filter_tb = gtk_toolbar_new();
3066 gtk_toolbar_set_orientation(GTK_TOOLBAR(filter_tb),
3067 GTK_ORIENTATION_HORIZONTAL);
3068 #endif /* GTK_MAJOR_VERSION */
3069 gtk_widget_show(filter_tb);
3071 /* Create the "Filter:" button */
3072 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
3073 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
3074 gtk_widget_show(filter_bt);
3075 OBJECT_SET_DATA(top_level, E_FILT_BT_PTR_KEY, filter_bt);
3077 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_bt,
3078 "Open the \"Display Filter\" dialog, to edit/apply filters", "Private");
3080 /* Create the filter combobox */
3081 filter_cm = gtk_combo_new();
3083 gtk_combo_disable_activate(GTK_COMBO(filter_cm));
3084 gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
3085 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, filter_list);
3086 filter_te = GTK_COMBO(filter_cm)->entry;
3087 main_display_filter_widget=filter_te;
3088 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
3089 OBJECT_SET_DATA(filter_te, E_DFILTER_CM_KEY, filter_cm);
3090 OBJECT_SET_DATA(top_level, E_DFILTER_CM_KEY, filter_cm);
3091 SIGNAL_CONNECT(filter_te, "activate", filter_activate_cb, filter_te);
3092 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
3093 WIDGET_SET_SIZE(filter_cm, 400, -1);
3094 gtk_widget_show(filter_cm);
3095 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_cm,
3097 /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
3098 gtk_tooltips_set_tip(tooltips, filter_te,
3099 "Enter a display filter, or choose one of your recently used filters. "
3100 "The background color of this field is changed by a continuous syntax check (green is valid, red is invalid).",
3103 /* Create the "Add Expression..." button, to pop up a dialog
3104 for constructing filter comparison expressions. */
3105 filter_add_expr_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_ADD_EXPRESSION);
3106 OBJECT_SET_DATA(filter_tb, E_FILT_FILTER_TE_KEY, filter_te);
3107 SIGNAL_CONNECT(filter_add_expr_bt, "clicked", filter_add_expr_bt_cb, filter_tb);
3108 gtk_widget_show(filter_add_expr_bt);
3109 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_add_expr_bt,
3110 "Add an expression to this filter string", "Private");
3112 /* Create the "Clear" button */
3113 filter_reset = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLEAR);
3114 OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
3115 SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
3116 gtk_widget_show(filter_reset);
3117 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_reset,
3118 "Clear this filter string and update the display", "Private");
3120 /* Create the "Apply" button */
3121 filter_apply = BUTTON_NEW_FROM_STOCK(GTK_STOCK_APPLY);
3122 OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
3123 SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
3124 gtk_widget_show(filter_apply);
3125 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_apply,
3126 "Apply this filter string to the display", "Private");
3128 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
3129 * of any widget that ends up calling a callback which needs
3130 * that text entry pointer */
3131 set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
3132 set_menu_object_data("/Analyze/Display Filters...", E_FILT_TE_PTR_KEY,
3134 set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
3136 set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
3138 set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
3140 set_menu_object_data("/Analyze/Apply as Filter/... and Selected", E_DFILTER_TE_KEY,
3142 set_menu_object_data("/Analyze/Apply as Filter/... or Selected", E_DFILTER_TE_KEY,
3144 set_menu_object_data("/Analyze/Apply as Filter/... and not Selected", E_DFILTER_TE_KEY,
3146 set_menu_object_data("/Analyze/Apply as Filter/... or not Selected", E_DFILTER_TE_KEY,
3148 set_menu_object_data("/Analyze/Prepare a Filter/Selected", E_DFILTER_TE_KEY,
3150 set_menu_object_data("/Analyze/Prepare a Filter/Not Selected", E_DFILTER_TE_KEY,
3152 set_menu_object_data("/Analyze/Prepare a Filter/... and Selected", E_DFILTER_TE_KEY,
3154 set_menu_object_data("/Analyze/Prepare a Filter/... or Selected", E_DFILTER_TE_KEY,
3156 set_menu_object_data("/Analyze/Prepare a Filter/... and not Selected", E_DFILTER_TE_KEY,
3158 set_menu_object_data("/Analyze/Prepare a Filter/... or not Selected", E_DFILTER_TE_KEY,
3160 set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
3161 OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
3162 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
3164 /* info (main) statusbar */
3165 info_bar = info_bar_new();
3166 gtk_widget_show(info_bar);
3168 /* packets statusbar */
3169 packets_bar = packets_bar_new();
3170 gtk_widget_show(packets_bar);
3172 /* Filter/status hbox */
3173 stat_hbox = gtk_hbox_new(FALSE, 1);
3174 gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
3175 gtk_widget_show(stat_hbox);
3177 /* Pane for the statusbar */
3178 status_pane = gtk_hpaned_new();
3179 gtk_widget_show(status_pane);