aboutsummaryrefslogtreecommitdiffstats
path: root/gtk2/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2/main.c')
-rw-r--r--gtk2/main.c2625
1 files changed, 0 insertions, 2625 deletions
diff --git a/gtk2/main.c b/gtk2/main.c
deleted file mode 100644
index 96f8a1d9bd..0000000000
--- a/gtk2/main.c
+++ /dev/null
@@ -1,2625 +0,0 @@
-/* main.c
- *
- * $Id: main.c,v 1.19 2002/10/25 03:13:11 guy Exp $
- *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
- * Copyright 1998 Gerald Combs
- *
- * Richard Sharpe, 13-Feb-1999, added support for initializing structures
- * needed by dissect routines
- * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * To do:
- * - Graphs
- * - Playback window
- * - Multiple window support
- * - Add cut/copy/paste
- * - Create header parsing routines
- * - Make byte view selections more fancy?
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gtk/gtk.h>
-
-#include <string.h>
-#include <ctype.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_IO_H
-#include <io.h> /* open/close on win32 */
-#endif
-
-#ifdef HAVE_LIBPCAP
-#include <pcap.h>
-#endif
-
-#ifdef HAVE_LIBZ
-#include <zlib.h> /* to get the libz version number */
-#endif
-
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
-#ifdef HAVE_SOME_SNMP
-
-#ifdef HAVE_NET_SNMP
-#include <net-snmp/version.h>
-#endif /* HAVE_NET_SNMP */
-
-#ifdef HAVE_UCD_SNMP
-#include <ucd-snmp/version.h>
-#endif /* HAVE_UCD_SNMP */
-
-#endif /* HAVE_SOME_SNMP */
-
-#ifdef NEED_STRERROR_H
-#include "strerror.h"
-#endif
-
-#ifdef NEED_GETOPT_H
-#include "getopt.h"
-#endif
-
-#ifdef WIN32 /* Needed for console I/O */
-#include <fcntl.h>
-#include <conio.h>
-#endif
-
-#include <epan/epan.h>
-#include <epan/filesystem.h>
-#include <epan/epan_dissect.h>
-
-#include "main.h"
-#include <epan/timestamp.h>
-#include <epan/packet.h>
-#include "capture.h"
-#include "summary.h"
-#include "file.h"
-#include "filters.h"
-#include "prefs.h"
-#include "menu.h"
-#include "../menu.h"
-#include "color.h"
-#include "color_utils.h"
-#include "filter_prefs.h"
-#include "file_dlg.h"
-#include "column.h"
-#include "print.h"
-#include <epan/resolv.h>
-#ifdef HAVE_LIBPCAP
-#include "pcap-util.h"
-#endif
-#include "statusbar.h"
-#include "simple_dialog.h"
-#include "proto_draw.h"
-#include <epan/dfilter/dfilter.h>
-#include "keys.h"
-#include "packet_win.h"
-#include "gtkglobals.h"
-#include <epan/plugins.h>
-#include "colors.h"
-#include <epan/strutil.h>
-#include "register.h"
-#include "ringbuffer.h"
-#include "ui_util.h"
-#include "image/clist_ascend.xpm"
-#include "image/clist_descend.xpm"
-#include "../tap.h"
-#include "rpc_stat.h"
-#include "rpc_progs.h"
-#include "../packet-dcerpc.h"
-#include "dcerpc_stat.h"
-
-#ifdef WIN32
-#include "capture-wpcap.h"
-#endif
-
-typedef struct column_arrows {
- GtkWidget *table;
- GtkWidget *ascend_pm;
- GtkWidget *descend_pm;
-} column_arrows;
-
-capture_file cfile;
-GtkWidget *top_level, *packet_list, *tree_view, *byte_nb_ptr,
- *tv_scrollw, *pkt_scrollw;
-static GtkWidget *info_bar;
-PangoFontDescription *m_r_font, *m_b_font;
-static guint main_ctx, file_ctx, help_ctx;
-static GString *comp_info_str;
-gchar *ethereal_path = NULL;
-gchar *last_open_dir = NULL;
-gint root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
-
-ts_type timestamp_type = RELATIVE;
-
-/* Specifies the field currently selected in the GUI protocol tree */
-field_info *finfo_selected = NULL;
-
-#ifdef WIN32
-static gboolean has_no_console; /* TRUE if app has no console */
-static gboolean console_was_created; /* TRUE if console was created */
-static void create_console(void);
-static void destroy_console(void);
-static void console_log_handler(const char *log_domain,
- GLogLevelFlags log_level, const char *message, gpointer user_data);
-#endif
-
-static void create_main_window(gint, gint, gint, e_prefs*);
-
-#define E_DFILTER_CM_KEY "display_filter_combo"
-#define E_DFILTER_FL_KEY "display_filter_list"
-
-/* About Ethereal window */
-void
-about_ethereal( GtkWidget *w _U_, gpointer data _U_ ) {
- simple_dialog(ESD_TYPE_INFO, NULL,
- "Ethereal - Network Protocol Analyzer\n"
- "Version " VERSION " (C) 1998-2002 Gerald Combs <gerald@ethereal.com>\n"
- "Compiled %s\n\n"
-
- "Check the man page for complete documentation and\n"
- "for the list of contributors.\n"
-
- "\nSee http://www.ethereal.com/ for more information.",
- comp_info_str->str);
-}
-
-void
-set_fonts(PangoFontDescription *regular, PangoFontDescription *bold)
-{
- /* Yes, assert. The code that loads the font should check
- * for NULL and provide its own error message. */
- g_assert(m_r_font && m_b_font);
- m_r_font = regular;
- m_b_font = bold;
-}
-
-
-/* Match selected byte pattern */
-static void
-match_selected_cb_do(gpointer data, int action, gchar *text)
-{
- GtkWidget *filter_te;
- char *cur_filter, *new_filter;
-
- if (!text)
- return;
- g_assert(data);
- filter_te = gtk_object_get_data(GTK_OBJECT(data), E_DFILTER_TE_KEY);
- g_assert(filter_te);
-
- cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
-
- switch (action&MATCH_SELECTED_MASK) {
-
- case MATCH_SELECTED_REPLACE:
- new_filter = g_strdup(text);
- break;
-
- case MATCH_SELECTED_AND:
- if ((!cur_filter) || (0 == strlen(cur_filter)))
- new_filter = g_strdup(text);
- else
- new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
- break;
-
- case MATCH_SELECTED_OR:
- if ((!cur_filter) || (0 == strlen(cur_filter)))
- new_filter = g_strdup(text);
- else
- new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
- break;
-
- case MATCH_SELECTED_NOT:
- new_filter = g_strconcat("!(", text, ")", NULL);
- break;
-
- case MATCH_SELECTED_AND_NOT:
- if ((!cur_filter) || (0 == strlen(cur_filter)))
- new_filter = g_strconcat("!(", text, ")", NULL);
- else
- new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
- break;
-
- case MATCH_SELECTED_OR_NOT:
- if ((!cur_filter) || (0 == strlen(cur_filter)))
- new_filter = g_strconcat("!(", text, ")", NULL);
- else
- new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
- break;
-
- default:
- g_assert_not_reached();
- new_filter = NULL;
- break;
- }
-
- /* Free up the copy we got of the old filter text. */
- g_free(cur_filter);
-
- /* create a new one and set the display filter entry accordingly */
- gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
-
- /* Run the display filter so it goes in effect. */
- if (action&MATCH_SELECTED_APPLY_NOW)
- filter_packets(&cfile, new_filter);
-
- /* Free up the new filter text. */
- g_free(new_filter);
-
- /* Free up the generated text we were handed. */
- g_free(text);
-}
-
-void
-match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR_NOT,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_REPLACE,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_NOT,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND_NOT,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
- void
-prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
-{
- if (finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR_NOT,
- proto_alloc_dfilter_string(finfo_selected,
- cfile.pd));
-}
-
-static gchar *
-get_text_from_packet_list(gpointer data)
-{
- gint row = (gint)gtk_object_get_data(GTK_OBJECT(data),
- E_MPACKET_LIST_ROW_KEY);
- gint column = (gint)gtk_object_get_data(GTK_OBJECT(data),
- E_MPACKET_LIST_COL_KEY);
- frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
- epan_dissect_t *edt;
- gchar *buf=NULL;
- int len;
- int err;
-
- if (fdata != NULL) {
- /* XXX - do something with "err" */
- wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
- cfile.pd, fdata->cap_len, &err);
-
- edt = epan_dissect_new(FALSE, FALSE);
- epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
- &cfile.cinfo);
- epan_dissect_fill_in_columns(edt);
-
- if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
- strlen(cfile.cinfo.col_expr_val[column]) != 0) {
- len = strlen(cfile.cinfo.col_expr[column]) +
- strlen(cfile.cinfo.col_expr_val[column]) + 5;
- buf = g_malloc0(len);
- snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
- cfile.cinfo.col_expr_val[column]);
- }
-
- epan_dissect_free(edt);
- }
-
- return buf;
-}
-
- void
-match_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-match_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-match_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-match_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-match_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-match_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
- void
-prepare_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_REPLACE,
- get_text_from_packet_list(data));
-}
-
- void
-prepare_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND,
- get_text_from_packet_list(data));
-}
-
- void
-prepare_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_NOT,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND_NOT,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR_NOT,
- get_text_from_packet_list(data));
-}
-
-/* Run the current display filter on the current packet set, and
- redisplay. */
-static void
-filter_activate_cb(GtkWidget *w, gpointer data)
-{
- GtkCombo *filter_cm = gtk_object_get_data(GTK_OBJECT(w),
- E_DFILTER_CM_KEY);
- GList *filter_list = gtk_object_get_data(GTK_OBJECT(filter_cm),
- E_DFILTER_FL_KEY);
- GList *li;
- gboolean add_filter = TRUE;
- gboolean free_filter = TRUE;
- char *s;
-
- g_assert(data);
- s = g_strdup(gtk_entry_get_text(GTK_ENTRY(data)));
-
- /* GtkCombos don't let us get at their list contents easily, so we maintain
- our own filter list, and feed it to gtk_combo_set_popdown_strings when
- a new filter is added. */
- if (filter_packets(&cfile, s)) {
- li = g_list_first(filter_list);
- while (li) {
- if (li->data && strcmp(s, li->data) == 0)
- add_filter = FALSE;
- li = li->next;
- }
-
- if (add_filter) {
- free_filter = FALSE;
- filter_list = g_list_append(filter_list, s);
- gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
- gtk_combo_set_popdown_strings(filter_cm, filter_list);
- gtk_entry_set_text(GTK_ENTRY(filter_cm->entry),
- g_list_last(filter_list)->data);
- }
- }
- if (free_filter)
- g_free(s);
-}
-
-/* redisplay with no display filter */
-static void
-filter_reset_cb(GtkWidget *w, gpointer data _U_)
-{
- GtkWidget *filter_te = NULL;
-
- if ((filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY))) {
- gtk_entry_set_text(GTK_ENTRY(filter_te), "");
- }
- filter_packets(&cfile, NULL);
-}
-
-/* GTKClist compare routine, overrides default to allow numeric comparison */
-static gint
-packet_list_compare(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
-{
- /* Get row text strings */
- char *text1 = GTK_CELL_TEXT (((GtkCListRow *)ptr1)->cell[clist->sort_column])->text;
- char *text2 = GTK_CELL_TEXT (((GtkCListRow *)ptr2)->cell[clist->sort_column])->text;
-
- /* Attempt to convert to numbers */
- double num1 = atof(text1);
- double num2 = atof(text2);
-
- gint col_fmt = cfile.cinfo.col_fmt[clist->sort_column];
-
- if ((col_fmt == COL_NUMBER) || (col_fmt == COL_REL_TIME) ||
- (col_fmt == COL_DELTA_TIME) ||
- ((col_fmt == COL_CLS_TIME) && (timestamp_type == RELATIVE)) ||
- ((col_fmt == COL_CLS_TIME) && (timestamp_type == DELTA)) ||
- (col_fmt == COL_UNRES_SRC_PORT) || (col_fmt == COL_UNRES_DST_PORT) ||
- ((num1 != 0) && (num2 != 0) && ((col_fmt == COL_DEF_SRC_PORT) ||
- (col_fmt == COL_RES_SRC_PORT) ||
- (col_fmt == COL_DEF_DST_PORT) ||
- (col_fmt == COL_RES_DST_PORT))) ||
- (col_fmt == COL_PACKET_LENGTH)) {
-
- /* Compare numeric column */
-
- if (num1 < num2)
- return -1;
- else if (num1 > num2)
- return 1;
- else
- return 0;
- }
-
- else {
-
- /* Compare text column */
- if (!text2)
- return (text1 != NULL);
-
- if (!text1)
- return -1;
-
- return strcmp(text1, text2);
- }
-}
-
-/* What to do when a column is clicked */
-static void
-packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
-{
- column_arrows *col_arrows = (column_arrows *) data;
- int i;
-
- gtk_clist_freeze(clist);
-
- for (i = 0; i < cfile.cinfo.num_cols; i++) {
- gtk_widget_hide(col_arrows[i].ascend_pm);
- gtk_widget_hide(col_arrows[i].descend_pm);
- }
-
- if (column == clist->sort_column) {
- if (clist->sort_type == GTK_SORT_ASCENDING) {
- clist->sort_type = GTK_SORT_DESCENDING;
- gtk_widget_show(col_arrows[column].descend_pm);
- } else {
- clist->sort_type = GTK_SORT_ASCENDING;
- gtk_widget_show(col_arrows[column].ascend_pm);
- }
- }
- else {
- clist->sort_type = GTK_SORT_ASCENDING;
- gtk_widget_show(col_arrows[column].ascend_pm);
- gtk_clist_set_sort_column(clist, column);
- }
- gtk_clist_thaw(clist);
-
- gtk_clist_sort(clist);
-}
-
-/* mark packets */
-static void
-set_frame_mark(gboolean set, frame_data *frame, gint row) {
- GdkColor fg, bg;
-
- if (row == -1)
- return;
- if (set) {
- mark_frame(&cfile, frame);
- color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
- color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
- gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
- gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
- } else {
- unmark_frame(&cfile, frame);
- gtk_clist_set_background(GTK_CLIST(packet_list), row, NULL);
- gtk_clist_set_foreground(GTK_CLIST(packet_list), row, NULL);
- }
- file_set_save_marked_sensitive();
-}
-
-static gint
-packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
-{
- GdkEventButton *event_button = (GdkEventButton *)event;
- gint row, column;
-
- if (w == NULL || event == NULL)
- return FALSE;
-
- if (event->type == GDK_BUTTON_PRESS &&
- gtk_clist_get_selection_info(GTK_CLIST(w), event_button->x,
- event_button->y,
- &row, &column)) {
- if (event_button->button == 2)
- {
- frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w),
- row);
- set_frame_mark(!fdata->flags.marked, fdata, row);
- return TRUE;
- }
- else if (event_button->button == 1) {
- gtk_clist_select_row(GTK_CLIST(w), row, column);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-void mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
- if (cfile.current_frame) {
- /* XXX hum, should better have a "cfile->current_row" here ... */
- set_frame_mark(!cfile.current_frame->flags.marked,
- cfile.current_frame,
- gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
- cfile.current_frame));
- }
-}
-
-static void mark_all_frames(gboolean set) {
- frame_data *fdata;
- for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
- set_frame_mark(set,
- fdata,
- gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
- }
-}
-
-void update_marked_frames(void) {
- frame_data *fdata;
- if (cfile.plist == NULL) return;
- for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
- if (fdata->flags.marked)
- set_frame_mark(TRUE,
- fdata,
- gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
- fdata));
- }
-}
-
-void mark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
- mark_all_frames(TRUE);
-}
-
-void unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
- mark_all_frames(FALSE);
-}
-
-/* What to do when a list item is selected/unselected */
-static void
-packet_list_select_cb(GtkWidget *w _U_, gint row, gint col _U_,
- gpointer evt _U_)
-{
- /* Remove the hex display tabbed pages */
- while( (gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), 0)))
- gtk_notebook_remove_page( GTK_NOTEBOOK(byte_nb_ptr), 0);
-
- select_packet(&cfile, row);
-}
-
-
-static void
-packet_list_unselect_cb(GtkWidget *w _U_, gint row _U_, gint col _U_,
- gpointer evt _U_) {
-
- unselect_packet(&cfile);
-}
-
-
-static void
-tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
-{
- field_info *finfo;
- gchar *help_str = NULL;
- gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
- N < 4294967296 */
- gboolean has_blurb = FALSE;
- guint length = 0, byte_len;
- GtkWidget *byte_view;
- const guint8 *byte_data;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- /* if something is selected */
- if (gtk_tree_selection_get_selected(sel, &model, &iter))
- {
- gtk_tree_model_get(model, &iter, 1, &finfo, -1);
- if (!finfo) return;
-
- set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
-
- byte_view = get_notebook_bv_ptr(byte_nb_ptr);
- byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
- g_assert(byte_data != NULL);
-
- finfo_selected = finfo;
- set_menus_for_selected_tree_row(TRUE);
-
- if (finfo->hfinfo) {
- if (finfo->hfinfo->blurb != NULL &&
- finfo->hfinfo->blurb[0] != '\0') {
- has_blurb = TRUE;
- length = strlen(finfo->hfinfo->blurb);
- } else {
- length = strlen(finfo->hfinfo->name);
- }
- if (finfo->length == 0) {
- len_str[0] = '\0';
- } else if (finfo->length == 1) {
- strcpy (len_str, ", 1 byte");
- } else {
- snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
- }
-
- statusbar_pop_field_msg(); /* get rid of current help msg */
- if (length) {
- length += strlen(finfo->hfinfo->abbrev) + strlen(len_str) + 10;
- help_str = g_malloc(sizeof(gchar) * length);
- sprintf(help_str, "%s (%s)%s",
- (has_blurb) ? finfo->hfinfo->blurb :
- finfo->hfinfo->name,
- finfo->hfinfo->abbrev, len_str);
- statusbar_push_field_msg(help_str);
- g_free(help_str);
- } else {
- /*
- * Don't show anything if the field name is zero-length;
- * the pseudo-field for "proto_tree_add_text()" is such
- * a field, and we don't want "Text (text)" showing up
- * on the status line if you've selected such a field.
- *
- * XXX - there are zero-length fields for which we *do*
- * want to show the field name.
- *
- * XXX - perhaps the name and abbrev field should be null
- * pointers rather than null strings for that pseudo-field,
- * but we'd have to add checks for null pointers in some
- * places if we did that.
- *
- * Or perhaps protocol tree items added with
- * "proto_tree_add_text()" should have -1 as the field index,
- * with no pseudo-field being used, but that might also
- * require special checks for -1 to be added.
- */
- statusbar_push_field_msg("");
- }
- }
-
- packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
- cfile.current_frame, finfo, byte_len);
- }
- else /* nothing selected */
- {
- /*
- * Which byte view is displaying the current protocol tree
- * row's data?
- */
- byte_view = get_notebook_bv_ptr(byte_nb_ptr);
- if (byte_view == NULL)
- return; /* none */
-
- byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
- if (byte_data == NULL)
- return; /* none */
-
- unselect_field();
- packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
- cfile.current_frame, NULL, byte_len);
- }
-}
-
-void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- if (cfile.edt->tree)
- collapse_all_tree(cfile.edt->tree, tree_view);
-}
-
-void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- if (cfile.edt->tree)
- expand_all_tree(cfile.edt->tree, tree_view);
-}
-
-void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- if (cfile.edt->tree) {
- guint32 tmp = g_resolv_flags;
- g_resolv_flags = RESOLV_ALL;
- proto_tree_draw(cfile.edt->tree, tree_view);
- g_resolv_flags = tmp;
- }
-}
-
-/* Set the selection mode of the packet list window. */
-void
-set_plist_sel_browse(gboolean val)
-{
- gboolean old_val;
-
- old_val =
- (GTK_CLIST(packet_list)->selection_mode == GTK_SELECTION_SINGLE);
-
- if (val == old_val) {
- /*
- * The mode isn't changing, so don't do anything.
- * In particular, don't gratuitiously unselect the
- * current packet.
- *
- * XXX - why do we have to unselect the current packet
- * ourselves? The documentation for the GtkCList at
- *
- * http://developer.gnome.org/doc/API/gtk/gtkclist.html
- *
- * says "Note that setting the widget's selection mode to
- * one of GTK_SELECTION_BROWSE or GTK_SELECTION_SINGLE will
- * cause all the items in the GtkCList to become deselected."
- */
- return;
- }
-
- if (finfo_selected)
- unselect_packet(&cfile);
-
- /* Yeah, GTK uses "browse" in the case where we do not, but oh well. I think
- * "browse" in Ethereal makes more sense than "SINGLE" in GTK+ */
- if (val) {
- gtk_clist_set_selection_mode(GTK_CLIST(packet_list),
- GTK_SELECTION_SINGLE);
- }
- else {
- gtk_clist_set_selection_mode(GTK_CLIST(packet_list),
- GTK_SELECTION_BROWSE);
- }
-}
-
-/* Set the font of the packet list window. */
-void
-set_plist_font(PangoFontDescription *font)
-{
- int i;
-
- gtk_widget_modify_font(packet_list, font);
-
- /* Compute static column sizes to use during a "-S" capture, so that
- the columns don't resize during a live capture. */
- for (i = 0; i < cfile.cinfo.num_cols; i++) {
- cfile.cinfo.col_width[i] = gdk_string_width(gdk_font_from_description(font),
- get_column_longest_string(get_column_format(i)));
- }
-}
-
-/*
- * Push a message referring to file access onto the statusbar.
- */
-void
-statusbar_push_file_msg(gchar *msg)
-{
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
-}
-
-/*
- * Pop a message referring to file access off the statusbar.
- */
-void
-statusbar_pop_file_msg(void)
-{
- gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
-}
-
-/*
- * XXX - do we need multiple statusbar contexts?
- */
-
-/*
- * Push a message referring to the currently-selected field onto the statusbar.
- */
-void
-statusbar_push_field_msg(gchar *msg)
-{
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
-}
-
-/*
- * Pop a message referring to the currently-selected field off the statusbar.
- */
-void
-statusbar_pop_field_msg(void)
-{
- gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
-}
-
-static gboolean
-do_quit(void)
-{
- /* XXX - should we check whether the capture file is an
- unsaved temporary file for a live capture and, if so,
- pop up a "do you want to exit without saving the capture
- file?" dialog, and then just return, leaving said dialog
- box to forcibly quit if the user clicks "OK"?
-
- If so, note that this should be done in a subroutine that
- returns TRUE if we do so, and FALSE otherwise, and if it
- returns TRUE we should return TRUE without nuking anything.
-
- Note that, if we do that, we might also want to check if
- an "Update list of packets in real time" capture is in
- progress and, if so, ask whether they want to terminate
- the capture and discard it, and return TRUE, before nuking
- any child capture, if they say they don't want to do so. */
-
-#ifdef HAVE_LIBPCAP
- /* Nuke any child capture in progress. */
- kill_capture_child();
-#endif
-
- /* Are we in the middle of reading a capture? */
- if (cfile.state == FILE_READ_IN_PROGRESS) {
- /* Yes, so we can't just close the file and quit, as
- that may yank the rug out from under the read in
- progress; instead, just set the state to
- "FILE_READ_ABORTED" and return - the code doing the read
- will check for that and, if it sees that, will clean
- up and quit. */
- cfile.state = FILE_READ_ABORTED;
-
- /* Say that the window should *not* be deleted;
- that'll be done by the code that cleans up. */
- return TRUE;
- } else {
- /* Close any capture file we have open; on some OSes, you
- can't unlink a temporary capture file if you have it
- open.
- "close_cap_file()" will unlink it after closing it if
- it's a temporary file.
-
- We do this here, rather than after the main loop returns,
- as, after the main loop returns, the main window may have
- been destroyed (if this is called due to a "destroy"
- even on the main window rather than due to the user
- selecting a menu item), and there may be a crash
- or other problem when "close_cap_file()" tries to
- clean up stuff in the main window.
-
- XXX - is there a better place to put this?
- Or should we have a routine that *just* closes the
- capture file, and doesn't do anything with the UI,
- which we'd call here, and another routine that
- calls that routine and also cleans up the UI, which
- we'd call elsewhere? */
- close_cap_file(&cfile);
-
- /* Exit by leaving the main loop, so that any quit functions
- we registered get called. */
- gtk_main_quit();
-
- /* Say that the window should be deleted. */
- return FALSE;
- }
-}
-
-static gboolean
-main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_,
- gpointer data _U_)
-{
- gint desk_x, desk_y;
-
- /* Try to grab our geometry */
- gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
- if (gdk_window_get_deskrelative_origin(top_level->window,
- &desk_x, &desk_y)) {
- if (desk_x <= root_x && desk_y <= root_y) {
- root_x = desk_x;
- root_y = desk_y;
- }
- }
-
- /* XXX - Is this the "approved" method? */
- gdk_window_get_size(top_level->window, &top_width, &top_height);
-
- /* "do_quit()" indicates whether the main window should be deleted. */
- return do_quit();
-}
-
-void
-file_quit_cmd_cb (GtkWidget *widget _U_, gpointer data _U_)
-{
- do_quit();
-}
-
-static void
-print_usage(gboolean print_ver) {
-
- if (print_ver) {
- fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
- comp_info_str->str);
- }
-#ifdef HAVE_LIBPCAP
- fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
- PACKAGE);
- fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
- fprintf(stderr, "\t[ -c <count> ] [ -f <capture filter> ] [ -i <interface> ]\n");
- fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
- fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
- fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
- fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
- fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n");
-#else
- fprintf(stderr, "\n%s [ -vh ] [ -B <byte view height> ] [ -m <medium font> ]\n",
- PACKAGE);
- fprintf(stderr, "\t[ -n ] [ -N <resolving> ]\n");
- fprintf(stderr, "\t[ -o <preference setting> ... [ -P <packet list height> ]\n");
- fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -t <time stamp format> ]\n");
- fprintf(stderr, "\t[ -T <tree view height> ] [ <infile> ]\n");
-#endif
-}
-
-static void
-show_version(void)
-{
-#ifdef WIN32
- create_console();
-#endif
-
- printf("%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
-}
-
-static int
-get_positive_int(const char *string, const char *name)
-{
- long number;
- char *p;
-
- number = strtol(string, &p, 10);
- if (p == string || *p != '\0') {
- fprintf(stderr, "ethereal: The specified %s \"%s\" is not a decimal number\n",
- name, string);
- exit(1);
- }
- if (number < 0) {
- fprintf(stderr, "ethereal: The specified %s \"%s\" is a negative number\n",
- name, string);
- exit(1);
- }
- if (number == 0) {
- fprintf(stderr, "ethereal: The specified %s \"%s\" is zero\n",
- name, string);
- exit(1);
- }
- if (number > INT_MAX) {
- fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
- name, string, INT_MAX);
- exit(1);
- }
- return number;
-}
-
-#ifdef HAVE_LIBPCAP
-/*
- * Given a string of the form "<autostop criterion>:<value>", as might appear
- * as an argument to a "-a" option, parse it and set the criterion in
- * question. Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-set_autostop_criterion(const char *autostoparg)
-{
- guchar *p, *colonp;
-
- colonp = strchr(autostoparg, ':');
- if (colonp == NULL)
- return FALSE;
-
- p = colonp;
- *p++ = '\0';
-
- /*
- * Skip over any white space (there probably won't be any, but
- * as we allow it in the preferences file, we might as well
- * allow it here).
- */
- while (isspace(*p))
- p++;
- if (*p == '\0') {
- /*
- * Put the colon back, so if our caller uses, in an
- * error message, the string they passed us, the message
- * looks correct.
- */
- *colonp = ':';
- return FALSE;
- }
- if (strcmp(autostoparg,"duration") == 0) {
- capture_opts.has_autostop_duration = TRUE;
- capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
- } else if (strcmp(autostoparg,"filesize") == 0) {
- capture_opts.has_autostop_filesize = TRUE;
- capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
- } else {
- return FALSE;
- }
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-#endif
-
-#ifdef WIN32
-/*
- * Once every 3 seconds we get a callback here which we use to update
- * the tap extensions. Since Gtk1 is single threaded we dont have to
- * worry about any locking or critical regions.
- * */
-static gint
-update_cb(gpointer data _U_)
-{
- draw_tap_listeners(FALSE);
- return 1;
-}
-#else
-
-/* if these three functions are copied to gtk1 ethereal, since gtk1 does not
- use threads all updte_thread_mutex can be dropped and protect/unprotect
- would just be empty functions.
-
- This allows gtk2-rpcstat.c and friends to be copied unmodified to
- gtk1-ethereal and it will just work.
- */
-static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
-gpointer
-update_thread(gpointer data _U_)
-{
- while(1){
- GTimeVal tv1, tv2;
- g_get_current_time(&tv1);
- g_static_mutex_lock(&update_thread_mutex);
- gdk_threads_enter();
- draw_tap_listeners(FALSE);
- gdk_threads_leave();
- g_static_mutex_unlock(&update_thread_mutex);
- g_thread_yield();
- g_get_current_time(&tv2);
- if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) > (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
- g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
- (tv2.tv_sec * 1000000 + tv2.tv_usec));
- }
- }
- return NULL;
-}
-#endif
-
-void
-protect_thread_critical_region(void)
-{
-#ifndef WIN32
- g_static_mutex_lock(&update_thread_mutex);
-#endif
-}
-void
-unprotect_thread_critical_region(void)
-{
-#ifndef WIN32
- g_static_mutex_unlock(&update_thread_mutex);
-#endif
-}
-
-/* And now our feature presentation... [ fade to music ] */
-int
-main(int argc, char *argv[])
-{
-#ifdef HAVE_LIBPCAP
- char *command_name;
-#endif
- char *s;
- int i;
- int opt;
- extern char *optarg;
- gboolean arg_error = FALSE;
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_VERSION
- extern char pcap_version[];
-#endif /* HAVE_PCAP_VERSION */
-#endif /* HAVE_LIBPCAP */
-
-#ifdef WIN32
- WSADATA wsaData;
-
-# ifdef HAVE_SOME_SNMP
- char *mib_path;
-# define MIB_PATH_APPEND "\\snmp\\mibs"
-# endif /* HAVE_SOME_SNMP */
-#endif /* WIN32 */
-
- char *gpf_path, *cf_path, *df_path;
- char *pf_path;
- int gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
- int err;
-#ifdef HAVE_LIBPCAP
- gboolean start_capture = FALSE;
- gchar *save_file = NULL;
- GList *if_list;
- gchar err_str[PCAP_ERRBUF_SIZE];
- gboolean stats_known;
- struct pcap_stat stats;
-#else
- gboolean capture_option_specified = FALSE;
-#endif
- gint pl_size = 280, tv_size = 95, bv_size = 75;
- gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
- dfilter_t *rfcode = NULL;
- gboolean rfilter_parse_failed = FALSE;
- e_prefs *prefs;
- char badopt;
- gint desk_x, desk_y;
- gboolean prefs_write_needed = FALSE;
-
-
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:vz:"
-
-#ifdef HAVE_LIBPCAP
-#ifdef WIN32
-#define OPTSTRING_CHILD "W:Z:"
-#else
-#define OPTSTRING_CHILD "W:"
-#endif /* WIN32 */
-#else
-#define OPTSTRING_CHILD ""
-#endif /* HAVE_LIBPCAP */
-
- char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
- OPTSTRING_INIT;
-
- ethereal_path = argv[0];
-
-#ifdef WIN32
- /* Arrange that if we have no console window, and a GLib message logging
- routine is called to log a message, we pop up a console window.
-
- We do that by inserting our own handler for all messages logged
- to the default domain; that handler pops up a console if necessary,
- and then calls the default handler. */
- g_log_set_handler(NULL,
- G_LOG_LEVEL_ERROR|
- G_LOG_LEVEL_CRITICAL|
- G_LOG_LEVEL_WARNING|
- G_LOG_LEVEL_MESSAGE|
- G_LOG_LEVEL_INFO|
- G_LOG_LEVEL_DEBUG|
- G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION,
- console_log_handler, NULL);
-#endif
-
-#ifdef HAVE_LIBPCAP
- command_name = get_basename(ethereal_path);
- /* Set "capture_child" to indicate whether this is going to be a child
- process for a "-S" capture. */
- capture_child = (strcmp(command_name, CHILD_NAME) == 0);
- if (capture_child)
- strcat(optstring, OPTSTRING_CHILD);
-#endif
-
- /* Register all dissectors; we must do this before checking for the
- "-G" flag, as the "-G" flag dumps information registered by the
- dissectors, and we must do it before we read the preferences, in
- case any dissectors register preferences. */
- epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
-
- /* Now register the preferences for any non-dissector modules.
- We must do that before we read the preferences as well. */
- prefs_register_modules();
-
- /* If invoked with the "-G" flag, we dump out information based on
- the argument to the "-G" flag; if no argument is specified,
- for backwards compatibility we dump out a glossary of display
- filter symbols.
-
- We must do this before calling "gtk_init()", because "gtk_init()"
- tries to open an X display, and we don't want to have to do any X
- stuff just to do a build.
-
- Given that we call "gtk_init()" before doing the regular argument
- list processing, so that it can handle X and GTK+ arguments and
- remove them from the list at which we look, this means we must do
- this before doing the regular argument list processing, as well.
-
- This means that:
-
- you must give the "-G" flag as the first flag on the command line;
-
- you must give it as "-G", nothing more, nothing less;
-
- the first argument after the "-G" flag, if present, will be used
- to specify the information to dump;
-
- arguments after that will not be used. */
- if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
- if (argc == 2)
- proto_registrar_dump_fields();
- else {
- if (strcmp(argv[2], "fields") == 0)
- proto_registrar_dump_fields();
- else if (strcmp(argv[2], "protocols") == 0)
- proto_registrar_dump_protocols();
- else {
- fprintf(stderr, "tethereal: Invalid \"%s\" option for -G flag\n",
- argv[2]);
- exit(1);
- }
- }
- exit(0);
- }
-
- /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
-#ifndef WIN32
- /* if we have thread support via glib2 try to start the low level
- thread to update applications asynchronously
- */
- if(GLIB_MAJOR_VERSION>=2){
-#ifdef G_THREADS_ENABLED
- GThread *ut;
- g_thread_init(NULL);
- gdk_threads_init();
- ut=g_thread_create(update_thread, NULL, FALSE, NULL);
- g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
-#endif /* G_THREADS_ENABLED */
- }
-#else /* WIN32 */
- /* this is to keep tap extensions updating once every 3 seconds */
- gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
-#endif /* WIN32 */
-
- /* Set the current locale according to the program environment.
- * We haven't localized anything, but some GTK widgets are localized
- * (the file selection dialogue, for example).
- * This also sets the C-language locale to the native environment. */
- gtk_set_locale();
-
- /* Let GTK get its args */
- gtk_init (&argc, &argv);
-
- /* Read the preference files. */
- prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
-
-#ifdef HAVE_LIBPCAP
- capture_opts.has_snaplen = FALSE;
- capture_opts.snaplen = MIN_PACKET_SIZE;
- capture_opts.has_autostop_count = FALSE;
- capture_opts.autostop_count = 1;
- capture_opts.has_autostop_duration = FALSE;
- capture_opts.autostop_duration = 1;
- capture_opts.has_autostop_filesize = FALSE;
- capture_opts.autostop_filesize = 1;
- capture_opts.ringbuffer_on = FALSE;
- capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
-
- /* If this is a capture child process, it should pay no attention
- to the "prefs.capture_prom_mode" setting in the preferences file;
- it should do what the parent process tells it to do, and if
- the parent process wants it not to run in promiscuous mode, it'll
- tell it so with a "-p" flag.
-
- Otherwise, set promiscuous mode from the preferences setting. */
- if (capture_child)
- capture_opts.promisc_mode = TRUE;
- else
- capture_opts.promisc_mode = prefs->capture_prom_mode;
-
- /* Set "Update list of packets in real time" mode from the preferences
- setting. */
- capture_opts.sync_mode = prefs->capture_real_time;
-
- /* And do the same for "Automatic scrolling in live capture" mode. */
- auto_scroll_live = prefs->capture_auto_scroll;
-#endif
-
- /* Set the name resolution code's flags from the preferences. */
- g_resolv_flags = prefs->name_resolve;
-
- /* Read the capture filter file. */
- read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
-
- /* Read the display filter file. */
- read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
-
- init_cap_file(&cfile);
-
- /* Assemble the compile-time options */
- comp_info_str = g_string_new("");
-
- g_string_append(comp_info_str, "with ");
-#ifdef GTK_MAJOR_VERSION
- g_string_sprintfa(comp_info_str,
- "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
- GTK_MICRO_VERSION);
-#else
- g_string_sprintfa(comp_info_str,
- "GTK+ (version unknown)");
-#endif
-
- g_string_append(comp_info_str, ", with ");
-#ifdef GLIB_MAJOR_VERSION
- g_string_sprintfa(comp_info_str,
- "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
- GLIB_MICRO_VERSION);
-#else
- g_string_sprintfa(comp_info_str, "GLib (version unknown)");
-#endif
-
-#ifdef HAVE_LIBPCAP
- g_string_append(comp_info_str, ", with libpcap ");
-#ifdef HAVE_PCAP_VERSION
- g_string_append(comp_info_str, pcap_version);
-#else /* HAVE_PCAP_VERSION */
- g_string_append(comp_info_str, "(version unknown)");
-#endif /* HAVE_PCAP_VERSION */
-#else /* HAVE_LIBPCAP */
- g_string_append(comp_info_str, ", without libpcap");
-#endif /* HAVE_LIBPCAP */
-
-#ifdef HAVE_LIBZ
- g_string_append(comp_info_str, ", with libz ");
-#ifdef ZLIB_VERSION
- g_string_append(comp_info_str, ZLIB_VERSION);
-#else /* ZLIB_VERSION */
- g_string_append(comp_info_str, "(version unknown)");
-#endif /* ZLIB_VERSION */
-#else /* HAVE_LIBZ */
- g_string_append(comp_info_str, ", without libz");
-#endif /* HAVE_LIBZ */
-
-/* Oh, this is pretty. */
-/* Oh, ha. you think that was pretty. Try this:! --Wes */
-#ifdef HAVE_SOME_SNMP
-
-#ifdef HAVE_UCD_SNMP
- g_string_append(comp_info_str, ", with UCD-SNMP ");
- g_string_append(comp_info_str, VersionInfo);
-#endif /* HAVE_UCD_SNMP */
-
-#ifdef HAVE_NET_SNMP
- g_string_append(comp_info_str, ", with Net-SNMP ");
- g_string_append(comp_info_str, netsnmp_get_version());
-#endif /* HAVE_NET_SNMP */
-
-#else /* no SNMP library */
- g_string_append(comp_info_str, ", without UCD-SNMP or Net-SNMP");
-#endif /* HAVE_SOME_SNMP */
-
- /* Now get our args */
- while ((opt = getopt(argc, argv, optstring)) != -1) {
- switch (opt) {
- case 'a': /* autostop criteria */
-#ifdef HAVE_LIBPCAP
- if (set_autostop_criterion(optarg) == FALSE) {
- fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
- exit(1);
- }
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'b': /* Ringbuffer option */
-#ifdef HAVE_LIBPCAP
- capture_opts.ringbuffer_on = TRUE;
- capture_opts.ringbuffer_num_files =
- get_positive_int(optarg, "number of ring buffer files");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'B': /* Byte view pane height */
- bv_size = get_positive_int(optarg, "byte view pane height");
- break;
- case 'c': /* Capture xxx packets */
-#ifdef HAVE_LIBPCAP
- capture_opts.has_autostop_count = TRUE;
- capture_opts.autostop_count = get_positive_int(optarg, "packet count");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'f':
-#ifdef HAVE_LIBPCAP
- if (cfile.cfilter)
- g_free(cfile.cfilter);
- cfile.cfilter = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'h': /* Print help and exit */
- print_usage(TRUE);
- exit(0);
- break;
- case 'i': /* Use interface xxx */
-#ifdef HAVE_LIBPCAP
- cfile.iface = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'k': /* Start capture immediately */
-#ifdef HAVE_LIBPCAP
- start_capture = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'l': /* Automatic scrolling in live capture mode */
-#ifdef HAVE_LIBPCAP
- auto_scroll_live = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'm': /* Fixed-width font for the display */
- if (prefs->gui_font_name != NULL)
- g_free(prefs->gui_font_name);
- prefs->gui_font_name = g_strdup(optarg);
- break;
- case 'n': /* No name resolution */
- g_resolv_flags = RESOLV_NONE;
- break;
- case 'N': /* Select what types of addresses/port #s to resolve */
- if (g_resolv_flags == RESOLV_ALL)
- g_resolv_flags = RESOLV_NONE;
- badopt = string_to_name_resolve(optarg, &g_resolv_flags);
- if (badopt != '\0') {
- fprintf(stderr, "ethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
- badopt);
- exit(1);
- }
- break;
- case 'o': /* Override preference from command line */
- switch (prefs_set_pref(optarg)) {
-
- case PREFS_SET_SYNTAX_ERR:
- fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
- exit(1);
- break;
-
- case PREFS_SET_NO_SUCH_PREF:
- case PREFS_SET_OBSOLETE:
- fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
- optarg);
- exit(1);
- break;
- }
- break;
- case 'p': /* Don't capture in promiscuous mode */
-#ifdef HAVE_LIBPCAP
- capture_opts.promisc_mode = FALSE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'P': /* Packet list pane height */
- pl_size = get_positive_int(optarg, "packet list pane height");
- break;
- case 'Q': /* Quit after capture (just capture to file) */
-#ifdef HAVE_LIBPCAP
- quit_after_cap = 1;
- start_capture = TRUE; /*** -Q implies -k !! ***/
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'r': /* Read capture file xxx */
- /* We may set "last_open_dir" to "cf_name", and if we change
- "last_open_dir" later, we free the old value, so we have to
- set "cf_name" to something that's been allocated. */
- cf_name = g_strdup(optarg);
- break;
- case 'R': /* Read file filter */
- rfilter = optarg;
- break;
- case 's': /* Set the snapshot (capture) length */
-#ifdef HAVE_LIBPCAP
- capture_opts.has_snaplen = TRUE;
- capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'S': /* "Sync" mode: used for following file ala tail -f */
-#ifdef HAVE_LIBPCAP
- capture_opts.sync_mode = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 't': /* Time stamp type */
- if (strcmp(optarg, "r") == 0)
- timestamp_type = RELATIVE;
- else if (strcmp(optarg, "a") == 0)
- timestamp_type = ABSOLUTE;
- else if (strcmp(optarg, "ad") == 0)
- timestamp_type = ABSOLUTE_WITH_DATE;
- else if (strcmp(optarg, "d") == 0)
- timestamp_type = DELTA;
- else {
- fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
- optarg);
- fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
- fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
- exit(1);
- }
- break;
- case 'T': /* Tree view pane height */
- tv_size = get_positive_int(optarg, "tree view pane height");
- break;
- case 'v': /* Show version and exit */
- show_version();
-#ifdef WIN32
- if (console_was_created)
- destroy_console();
-#endif
- exit(0);
- break;
- case 'w': /* Write to capture file xxx */
-#ifdef HAVE_LIBPCAP
- save_file = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
-#ifdef HAVE_LIBPCAP
- /* This is a hidden option supporting Sync mode, so we don't set
- * the error flags for the user in the non-libpcap case.
- */
- case 'W': /* Write to capture file FD xxx */
- cfile.save_file_fd = atoi(optarg);
- break;
-#endif
-
- case 'z':
- if(!strncmp(optarg,"rpc,",4)){
- if(!strncmp(optarg,"rpc,rtt,",8)){
- int rpcprogram, rpcversion;
- int pos=0;
- if(sscanf(optarg,"rpc,rtt,%d,%d,%n",&rpcprogram,&rpcversion,&pos)==2){
- if(pos){
- gtk_rpcstat_init(rpcprogram,rpcversion,optarg+pos);
- } else {
- gtk_rpcstat_init(rpcprogram,rpcversion,NULL);
- }
- } else {
- fprintf(stderr, "ethereal: invalid \"-z rpc,rtt,<program>,<version>[,<filter>]\" argument\n");
- exit(1);
- }
- } else if(!strncmp(optarg,"rpc,programs",12)){
- gtk_rpcprogs_init();
- } else {
- fprintf(stderr, "ethereal: invalid -z argument. Argument must be one of:\n");
- fprintf(stderr, " \"-z rpc,rtt,<program>,<version>[,<filter>]\"\n");
- fprintf(stderr, " \"-z rpc,programs\"\n");
- exit(1);
- }
- } else if(!strncmp(optarg,"dcerpc,",7)){
- if(!strncmp(optarg,"dcerpc,rtt,",11)){
- e_uuid_t uuid;
- int d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
- int major, minor;
- int pos=0;
- if(sscanf(optarg,"dcerpc,rtt,%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d%n", &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos)==13){
- uuid.Data1=d1;
- uuid.Data2=d2;
- uuid.Data3=d3;
- uuid.Data4[0]=d40;
- uuid.Data4[1]=d41;
- uuid.Data4[2]=d42;
- uuid.Data4[3]=d43;
- uuid.Data4[4]=d44;
- uuid.Data4[5]=d45;
- uuid.Data4[6]=d46;
- uuid.Data4[7]=d47;
- if(pos){
- gtk_dcerpcstat_init(&uuid,major,minor,optarg+pos);
- } else {
- gtk_dcerpcstat_init(&uuid,major,minor,NULL);
- }
- } else {
- fprintf(stderr, "ethereal: invalid \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
- exit(1);
- }
- } else {
- fprintf(stderr, "tethereal: invalid -z argument. Argument must be one of:\n");
- fprintf(stderr, " \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\"\n");
- exit(1);
- }
- } else {
- fprintf(stderr, "ethereal: invalid -z argument. Argument must be one of:\n");
- fprintf(stderr, " \"-z rpc,...\"\n");
- fprintf(stderr, " \"-z dcerpc,...\"\n");
- exit(1);
- }
- break;
-
-#ifdef _WIN32
-#ifdef HAVE_LIBPCAP
- /* Hidden option supporting Sync mode */
- case 'Z': /* Write to pipe FD XXX */
- /* associate stdout with pipe */
- i = atoi(optarg);
- if (dup2(i, 1) < 0) {
- fprintf(stderr, "Unable to dup pipe handle\n");
- exit(1);
- }
- break;
-#endif /* HAVE_LIBPCAP */
-#endif /* _WIN32 */
-
- default:
- case '?': /* Bad flag - print usage message */
- arg_error = TRUE;
- break;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc >= 1) {
- if (cf_name != NULL) {
- /*
- * Input file name specified with "-r" *and* specified as a regular
- * command-line argument.
- */
- arg_error = TRUE;
- } else {
- /*
- * Input file name not specified with "-r", and a command-line argument
- * was specified; treat it as the input file name.
- *
- * Yes, this is different from tethereal, where non-flag command-line
- * arguments are a filter, but this works better on GUI desktops
- * where a command can be specified to be run to open a particular
- * file - yes, you could have "-r" as the last part of the command,
- * but that's a bit ugly.
- */
- cf_name = g_strdup(argv[0]);
- }
- argc--;
- argv++;
- }
-
- if (argc != 0) {
- /*
- * Extra command line arguments were specified; complain.
- */
- fprintf(stderr, "Invalid argument: %s\n", argv[0]);
- arg_error = TRUE;
- }
- if (arg_error) {
- print_usage(FALSE);
- exit(1);
- }
-
-#ifdef HAVE_LIBPCAP
- if (capture_opts.ringbuffer_on) {
- /* Ring buffer works only under certain conditions:
- a) ring buffer does not work with temporary files;
- b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive -
- sync_mode takes precedence;
- c) it makes no sense to enable the ring buffer if the maximum
- file size is set to "infinite". */
- if (save_file == NULL) {
- fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
- capture_opts.ringbuffer_on = FALSE;
- }
- if (capture_opts.sync_mode) {
- fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
- capture_opts.ringbuffer_on = FALSE;
- }
- if (!capture_opts.has_autostop_filesize) {
- fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
- capture_opts.ringbuffer_on = FALSE;
- }
- }
-#endif
-
-#ifdef WIN32
- /* Load wpcap if possible */
- load_wpcap();
-
- /* Start windows sockets */
- WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-
-# ifdef HAVE_SOME_SNMP
- /* Set MIBDIRS so that the SNMP library can find its mibs. */
- /* XXX - Should we set MIBS or MIBFILES as well? */
-
- mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
- sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
- /* Amazingly enough, Windows does not provide setenv(). */
- if (getenv("MIBDIRS") == NULL)
- _putenv(mib_path);
- g_free(mib_path);
-
-# endif /* HAVE_UCD_SNMP */
-#endif /* WIN32 */
-
- /* Notify all registered modules that have had any of their preferences
- changed either from one of the preferences file or from the command
- line that their preferences have changed. */
- prefs_apply_all();
-
-#ifndef HAVE_LIBPCAP
- if (capture_option_specified)
- fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
-#endif
-#ifdef HAVE_LIBPCAP
- if (start_capture) {
- /* We're supposed to do a live capture; did the user specify an interface
- to use? */
- if (cfile.iface == NULL) {
- /* No - is a default specified in the preferences file? */
- if (prefs->capture_device != NULL) {
- /* Yes - use it. */
- cfile.iface = g_strdup(prefs->capture_device);
- } else {
- /* No - pick the first one from the list of interfaces. */
- if_list = get_interface_list(&err, err_str);
- if (if_list == NULL) {
- switch (err) {
-
- case CANT_GET_INTERFACE_LIST:
- fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
- err_str);
- break;
-
- case NO_INTERFACES_FOUND:
- fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
- break;
- }
- exit(2);
- }
- cfile.iface = g_strdup(if_list->data); /* first interface */
- free_interface_list(if_list);
- }
- }
- }
- if (capture_child) {
- if (cfile.save_file_fd == -1) {
- /* XXX - send this to the standard output as something our parent
- should put in an error message box? */
- fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
- exit(1);
- }
- }
-#endif
-
- /* Build the column format array */
- col_init(&cfile.cinfo, prefs->num_cols);
- for (i = 0; i < cfile.cinfo.num_cols; i++) {
- cfile.cinfo.col_fmt[i] = get_column_format(i);
- cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
- cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
- NUM_COL_FMTS);
- get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
- cfile.cinfo.col_data[i] = NULL;
- if (cfile.cinfo.col_fmt[i] == COL_INFO)
- cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
- else
- cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
- cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
- cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
- }
-
-#ifdef HAVE_LIBPCAP
- if (capture_opts.has_snaplen) {
- if (capture_opts.snaplen < 1)
- capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
- else if (capture_opts.snaplen < MIN_PACKET_SIZE)
- capture_opts.snaplen = MIN_PACKET_SIZE;
- }
-
- /* Check the value range of the ringbuffer_num_files parameter */
- if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
- capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
- else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
- capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
-#endif
-
- rc_file = get_persconffile_path(RC_FILE, FALSE);
- gtk_rc_parse(rc_file);
-
- /* Try to load the regular and boldface fixed-width fonts */
- m_r_font = pango_font_description_from_string(prefs->gui_font_name);
- m_b_font = pango_font_description_copy(m_r_font);
- pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
- if (m_r_font == NULL || m_b_font == NULL) {
- /* XXX - pop this up as a dialog box? no */
- if (m_r_font == NULL) {
-#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to Monospace 12\n",
- prefs->gui_font_name);
- } else {
- pango_font_description_free(m_r_font);
- }
- if (m_b_font == NULL) {
-#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: bold font %s not found - defaulting"
- " to Monospace 9\n", prefs->gui_font_name);
- } else {
- pango_font_description_free(m_b_font);
- }
- if ((m_r_font = pango_font_description_from_string("Monospace 9")) == NULL) {
- fprintf(stderr, "ethereal: Error: font Monospace 9 not found\n");
- exit(1);
- }
- if ((m_b_font = pango_font_description_copy(m_r_font)) == NULL) {
- fprintf(stderr, "ethereal: Error: font Monospace 9 bold not found\n");
- exit(1);
- }
- pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
- g_free(prefs->gui_font_name);
- prefs->gui_font_name = g_strdup("Monospace 9");
- }
-
- /* Call this for the side-effects that set_fonts() produces */
- set_fonts(m_r_font, m_b_font);
-
-
-#ifdef HAVE_LIBPCAP
- /* Is this a "child" ethereal, which is only supposed to pop up a
- capture box to let us stop the capture, and run a capture
- to a file that our parent will read? */
- if (!capture_child) {
-#endif
- /* No. Pop up the main window, and read in a capture file if
- we were told to. */
-
- create_main_window(pl_size, tv_size, bv_size, prefs);
- set_menus_for_capture_file(FALSE);
-
- colfilter_init();
-
- /* If we were given the name of a capture file, read it in now;
- we defer it until now, so that, if we can't open it, and pop
- up an alert box, the alert box is more likely to come up on
- top of the main window - but before the preference-file-error
- alert box, so, if we get one of those, it's more likely to come
- up on top of us. */
- if (cf_name) {
- if (rfilter != NULL) {
- if (!dfilter_compile(rfilter, &rfcode)) {
- simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
- rfilter_parse_failed = TRUE;
- }
- }
- if (!rfilter_parse_failed) {
- if ((err = open_cap_file(cf_name, FALSE, &cfile)) == 0) {
- /* "open_cap_file()" succeeded, so it closed the previous
- capture file, and thus destroyed any previous read filter
- attached to "cf". */
- cfile.rfcode = rfcode;
- switch (read_cap_file(&cfile, &err)) {
-
- case READ_SUCCESS:
- case READ_ERROR:
- /* Just because we got an error, that doesn't mean we were unable
- to read any of the file; we handle what we could get from the
- file. */
- break;
-
- case READ_ABORTED:
- /* Exit now. */
- gtk_exit(0);
- break;
- }
- /* Save the name of the containing directory specified in the
- path name, if any; we can write over cf_name, which is a
- good thing, given that "get_dirname()" does write over its
- argument. */
- s = get_dirname(cf_name);
- set_last_open_dir(s);
- g_free(cf_name);
- cf_name = NULL;
- } else {
- if (rfcode != NULL)
- dfilter_free(rfcode);
- cfile.rfcode = NULL;
- }
- }
- }
-#ifdef HAVE_LIBPCAP
- }
-#endif
-
- /* If the global preferences file exists but we failed to open it,
- pop up an alert box; we defer that until now, so that the alert
- box is more likely to come up on top of the main window. */
- if (gpf_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Could not open global preferences file\n\"%s\": %s.", gpf_path,
- strerror(gpf_open_errno));
- }
-
- /* If the user's preferences file exists but we failed to open it,
- pop up an alert box; we defer that until now, so that the alert
- box is more likely to come up on top of the main window. */
- if (pf_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Could not open your preferences file\n\"%s\": %s.", pf_path,
- strerror(pf_open_errno));
- g_free(pf_path);
- pf_path = NULL;
- }
-
- /* If the user's capture filter file exists but we failed to open it,
- pop up an alert box; we defer that until now, so that the alert
- box is more likely to come up on top of the main window. */
- if (cf_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Could not open your capture filter file\n\"%s\": %s.", cf_path,
- strerror(cf_open_errno));
- g_free(cf_path);
- }
-
- /* If the user's display filter file exists but we failed to open it,
- pop up an alert box; we defer that until now, so that the alert
- box is more likely to come up on top of the main window. */
- if (df_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Could not open your display filter file\n\"%s\": %s.", df_path,
- strerror(df_open_errno));
- g_free(df_path);
- }
-
-#ifdef HAVE_LIBPCAP
- if (capture_child) {
- /* This is the child process for a sync mode or fork mode capture,
- so just do the low-level work of a capture - don't create
- a temporary file and fork off *another* child process (so don't
- call "do_capture()"). */
-
- /* XXX - hand these stats to the parent process */
- capture(&stats_known, &stats);
-
- /* The capture is done; there's nothing more for us to do. */
- gtk_exit(0);
- } else {
- if (start_capture) {
- /* "-k" was specified; start a capture. */
- do_capture(save_file);
- if (save_file != NULL) {
- /* Save the directory name for future file dialogs. */
- s = get_dirname(save_file); /* Overwrites save_file */
- set_last_open_dir(s);
- g_free(save_file);
- save_file = NULL;
- }
- }
- else {
- set_menus_for_capture_in_progress(FALSE);
- }
- }
-#else
- set_menus_for_capture_in_progress(FALSE);
-#endif
-
- gtk_main();
-
- /* Try to save our geometry. GTK+ provides two routines to get a
- window's position relative to the X root window. If I understand the
- documentation correctly, gdk_window_get_deskrelative_origin applies
- mainly to Enlightenment and gdk_window_get_root_origin applies for
- all other WMs.
-
- The code below tries both routines, and picks the one that returns
- the upper-left-most coordinates.
-
- More info at:
-
-http://mail.gnome.org/archives/gtk-devel-list/2001-March/msg00289.html
-http://www.gtk.org/faq/#AEN600 */
-
- /* Re-read our saved preferences. */
- /* XXX - Move all of this into a separate function? */
- prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
-
- if (pf_path == NULL) {
- if (prefs->gui_geometry_save_position) {
- if (top_level->window != NULL) {
- gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
- if (gdk_window_get_deskrelative_origin(top_level->window,
- &desk_x, &desk_y)) {
- if (desk_x <= root_x && desk_y <= root_y) {
- root_x = desk_x;
- root_y = desk_y;
- }
- }
- }
- if (prefs->gui_geometry_main_x != root_x) {
- prefs->gui_geometry_main_x = root_x;
- prefs_write_needed = TRUE;
- }
- if (prefs->gui_geometry_main_y != root_y) {
- prefs->gui_geometry_main_y = root_y;
- prefs_write_needed = TRUE;
- }
- }
-
- if (prefs->gui_geometry_save_size) {
- if (top_level->window != NULL) {
- /* XXX - Is this the "approved" method? */
- gdk_window_get_size(top_level->window, &top_width, &top_height);
- }
- if (prefs->gui_geometry_main_width != top_width) {
- prefs->gui_geometry_main_width = top_width;
- prefs_write_needed = TRUE;
- }
- if (prefs->gui_geometry_main_height != top_height) {
- prefs->gui_geometry_main_height = top_height;
- prefs_write_needed = TRUE;
- }
- }
-
- if (prefs_write_needed) {
- write_prefs(&pf_path);
- }
- } else {
- /* Ignore errors silently */
- g_free(pf_path);
- }
-
- epan_cleanup();
- g_free(rc_file);
-
-#ifdef WIN32
- /* Shutdown windows sockets */
- WSACleanup();
-
- /* For some unknown reason, the "atexit()" call in "create_console()"
- doesn't arrange that "destroy_console()" be called when we exit,
- so we call it here if a console was created. */
- if (console_was_created)
- destroy_console();
-#endif
-
- gtk_exit(0);
-
- /* This isn't reached, but we need it to keep GCC from complaining
- that "main()" returns without returning a value - it knows that
- "exit()" never returns, but it doesn't know that "gtk_exit()"
- doesn't, as GTK+ doesn't declare it with the attribute
- "noreturn". */
- return 0; /* not reached */
-}
-
-#ifdef WIN32
-
-/* We build this as a GUI subsystem application on Win32, so
- "WinMain()", not "main()", gets called.
-
- Hack shamelessly stolen from the Win32 port of the GIMP. */
-#ifdef __GNUC__
-#define _stdcall __attribute__((stdcall))
-#endif
-
-int _stdcall
-WinMain (struct HINSTANCE__ *hInstance,
- struct HINSTANCE__ *hPrevInstance,
- char *lpszCmdLine,
- int nCmdShow)
-{
- has_no_console = TRUE;
- return main (__argc, __argv);
-}
-
-/*
- * If this application has no console window to which its standard output
- * would go, create one.
- */
-static void
-create_console(void)
-{
- if (has_no_console) {
- /* We have no console to which to print the version string, so
- create one and make it the standard input, output, and error. */
- if (!AllocConsole())
- return; /* couldn't create console */
- freopen("CONIN$", "r", stdin);
- freopen("CONOUT$", "w", stdout);
- freopen("CONOUT$", "w", stderr);
-
- /* Well, we have a console now. */
- has_no_console = FALSE;
- console_was_created = TRUE;
-
- /* Now register "destroy_console()" as a routine to be called just
- before the application exits, so that we can destroy the console
- after the user has typed a key (so that the console doesn't just
- disappear out from under them, giving the user no chance to see
- the message(s) we put in there). */
- atexit(destroy_console);
- }
-}
-
-static void
-destroy_console(void)
-{
- printf("\n\nPress any key to exit\n");
- _getch();
- FreeConsole();
-}
-
-/* This routine should not be necessary, at least as I read the GLib
- source code, as it looks as if GLib is, on Win32, *supposed* to
- create a console window into which to display its output.
-
- That doesn't happen, however. I suspect there's something completely
- broken about that code in GLib-for-Win32, and that it may be related
- to the breakage that forces us to just call "printf()" on the message
- rather than passing the message on to "g_log_default_handler()"
- (which is the routine that does the aforementioned non-functional
- console window creation). */
-static void
-console_log_handler(const char *log_domain, GLogLevelFlags log_level,
- const char *message, gpointer user_data)
-{
- create_console();
- if (console_was_created) {
- /* For some unknown reason, the above doesn't appear to actually cause
- anything to be sent to the standard output, so we'll just splat the
- message out directly, just to make sure it gets out. */
- printf("%s\n", message);
- } else
- g_log_default_handler(log_domain, log_level, message, user_data);
-}
-#endif
-
-static void
-create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
-{
- GtkWidget *main_vbox, *menubar, *u_pane, *l_pane,
- *stat_hbox, *column_lb,
- *filter_bt, *filter_cm, *filter_te,
- *filter_apply,
- *filter_reset;
- GList *filter_list = NULL;
- GtkAccelGroup *accel;
- GtkStyle *win_style;
- GdkBitmap *ascend_bm, *descend_bm;
- GdkPixmap *ascend_pm, *descend_pm;
- column_arrows *col_arrows;
- int i;
- /* Display filter construct dialog has an Apply button, and "OK" not
- only sets our text widget, it activates it (i.e., it causes us to
- filter the capture). */
- static construct_args_t args = {
- "Ethereal: Display Filter",
- TRUE,
- TRUE
- };
-
- /* Main window */
- top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_name(top_level, "main window");
- g_signal_connect(G_OBJECT(top_level), "delete_event",
- G_CALLBACK(main_window_delete_event_cb), NULL);
- g_signal_connect(G_OBJECT(top_level), "realize",
- G_CALLBACK (window_icon_realize_cb), NULL);
- gtk_window_set_title(GTK_WINDOW(top_level), "The Ethereal Network Analyzer");
- if (prefs->gui_geometry_save_position) {
- gtk_widget_set_uposition(GTK_WIDGET(top_level),
- prefs->gui_geometry_main_x,
- prefs->gui_geometry_main_y);
- }
- if (prefs->gui_geometry_save_size) {
- gtk_widget_set_size_request(GTK_WIDGET(top_level),
- prefs->gui_geometry_main_width,
- prefs->gui_geometry_main_height);
- } else {
- gtk_widget_set_size_request(GTK_WIDGET(top_level), DEF_WIDTH, -1);
- }
- gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
-
- /* Container for menu bar, paned windows and progress/info box */
- main_vbox = gtk_vbox_new(FALSE, 1);
- gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
- gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
- gtk_widget_show(main_vbox);
-
- /* Menu bar */
- get_main_menu(&menubar, &accel);
- gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
- gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
- gtk_widget_show(menubar);
-
- /* Panes for the packet list, tree, and byte view */
- u_pane = gtk_vpaned_new();
- gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
- l_pane = gtk_vpaned_new();
- gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
- gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
- gtk_widget_show(l_pane);
- gtk_paned_add2(GTK_PANED(u_pane), l_pane);
- gtk_widget_show(u_pane);
-
- /* Packet list */
- pkt_scrollw = scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(pkt_scrollw),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_widget_show(pkt_scrollw);
- gtk_paned_add1(GTK_PANED(u_pane), pkt_scrollw);
-
- packet_list = gtk_clist_new(cfile.cinfo.num_cols);
- /* Column titles are filled in below */
- gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
-
- col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) *
- cfile.cinfo.num_cols);
-
- set_plist_sel_browse(prefs->gui_plist_sel_browse);
- set_plist_font(m_r_font);
- gtk_widget_set_name(packet_list, "packet list");
- g_signal_connect(G_OBJECT(packet_list), "click-column",
- G_CALLBACK(packet_list_click_column_cb), col_arrows);
- g_signal_connect(G_OBJECT(packet_list), "select-row",
- G_CALLBACK(packet_list_select_cb), NULL);
- g_signal_connect(G_OBJECT(packet_list), "unselect-row",
- G_CALLBACK(packet_list_unselect_cb), NULL);
- for (i = 0; i < cfile.cinfo.num_cols; i++) {
- if (get_column_resize_type(cfile.cinfo.col_fmt[i]) != RESIZE_MANUAL)
- gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
-
- /* Right-justify the packet number column. */
- if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
- gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
- GTK_JUSTIFY_RIGHT);
- }
- gtk_widget_set_size_request(packet_list, -1, pl_size);
- g_signal_connect(G_OBJECT(packet_list), "button_press_event",
- G_CALLBACK(popup_menu_handler),
- gtk_object_get_data(GTK_OBJECT(popup_menu_object),
- PM_PACKET_LIST_KEY));
- g_signal_connect(G_OBJECT(packet_list), "button_press_event",
- G_CALLBACK(packet_list_button_pressed_cb), NULL);
- gtk_clist_set_compare_func(GTK_CLIST(packet_list), packet_list_compare);
- gtk_widget_show(packet_list);
-
- /* Tree view */
- create_tree_view(tv_size, prefs, l_pane, &tv_scrollw, &tree_view);
- g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view))),
- "changed", G_CALLBACK(tree_view_selection_changed_cb),
- NULL);
- g_signal_connect(G_OBJECT(tree_view), "button_press_event",
- G_CALLBACK(popup_menu_handler),
- gtk_object_get_data(GTK_OBJECT(popup_menu_object),
- PM_TREE_VIEW_KEY));
- gtk_widget_show(tree_view);
-
- /* Byte view. */
- byte_nb_ptr = create_byte_view(bv_size, l_pane);
-
- g_signal_connect(G_OBJECT(byte_nb_ptr), "button_press_event",
- G_CALLBACK(popup_menu_handler),
- gtk_object_get_data(GTK_OBJECT(popup_menu_object),
- PM_HEXDUMP_KEY));
-
- /* Filter/info box */
- stat_hbox = gtk_hbox_new(FALSE, 1);
- gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
- gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
- gtk_widget_show(stat_hbox);
-
- filter_bt = gtk_button_new_with_label("Filter:");
- g_signal_connect(G_OBJECT(filter_bt), "clicked",
- G_CALLBACK(display_filter_construct_cb), &args);
- gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
- gtk_widget_show(filter_bt);
-
- filter_cm = gtk_combo_new();
- filter_list = g_list_append (filter_list, "");
- gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
- gtk_combo_disable_activate(GTK_COMBO(filter_cm));
- gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
- gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
- filter_te = GTK_COMBO(filter_cm)->entry;
- gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
- gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
- gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
- g_signal_connect(G_OBJECT(filter_te), "activate",
- G_CALLBACK(filter_activate_cb), filter_te);
- gtk_widget_show(filter_cm);
-
- filter_reset = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
- gtk_object_set_data(GTK_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
- g_signal_connect(G_OBJECT(filter_reset), "clicked",
- G_CALLBACK(filter_reset_cb), NULL);
- gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
- gtk_widget_show(filter_reset);
-
- filter_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
- gtk_object_set_data(GTK_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
- g_signal_connect(G_OBJECT(filter_apply), "clicked",
- G_CALLBACK(filter_activate_cb), filter_te);
- gtk_box_pack_start(GTK_BOX(stat_hbox), filter_apply, FALSE, TRUE, 1);
- gtk_widget_show(filter_apply);
-
- /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
- * of any widget that ends up calling a callback which needs
- * that text entry pointer */
- set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
- set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/And Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/Or Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/And Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Match/Or Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/And Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/Or Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/And Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY,
- filter_te);
- gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_DFILTER_TE_KEY,
- filter_te);
- gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY,
- packet_list);
-
- info_bar = gtk_statusbar_new();
- main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
- file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
- help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
- gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
- gtk_widget_show(info_bar);
-
- gtk_widget_show(top_level);
-
- /* Fill in column titles. This must be done after the top level window
- is displayed. */
- win_style = gtk_widget_get_style(top_level);
- ascend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &ascend_bm,
- &win_style->bg[GTK_STATE_NORMAL],
- (gchar **)clist_ascend_xpm);
- descend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &descend_bm,
- &win_style->bg[GTK_STATE_NORMAL],
- (gchar **)clist_descend_xpm);
- for (i = 0; i < cfile.cinfo.num_cols; i++) {
- col_arrows[i].table = gtk_table_new(2, 2, FALSE);
- gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
- column_lb = gtk_label_new(cfile.cinfo.col_title[i]);
- gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2,
- GTK_SHRINK, GTK_SHRINK, 0, 0);
- gtk_widget_show(column_lb);
- col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
- gtk_table_attach(GTK_TABLE(col_arrows[i].table),
- col_arrows[i].ascend_pm,
- 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
- if (i == 0) {
- gtk_widget_show(col_arrows[i].ascend_pm);
- }
- col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
- gtk_table_attach(GTK_TABLE(col_arrows[i].table),
- col_arrows[i].descend_pm,
- 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
- gtk_clist_set_column_widget(GTK_CLIST(packet_list), i,
- col_arrows[i].table);
- gtk_widget_show(col_arrows[i].table);
- }
- gtk_clist_column_titles_show(GTK_CLIST(packet_list));
-}
-
-
-void
-set_last_open_dir(char *dirname)
-{
- int len;
-
- if (last_open_dir) {
- g_free(last_open_dir);
- }
-
- if (dirname) {
- len = strlen(dirname);
- if (dirname[len-1] == G_DIR_SEPARATOR) {
- last_open_dir = g_strconcat(dirname, NULL);
- }
- else {
- last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
- NULL);
- }
- }
- else {
- last_open_dir = NULL;
- }
-}