c496e250ceefb8548a22e5a5a92d7b01d959cee3
[obnox/wireshark/wip.git] / gtk / main.c
1 /* main.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
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
12  *
13  *
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.
18  *
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.
23  *
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.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <gtk/gtk.h>
34 #include <gdk/gdkkeysyms.h>
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <ctype.h>
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 #ifdef NEED_STRERROR_H
45 #include "strerror.h"
46 #endif
47
48 #ifdef HAVE_GETOPT_H
49 #include <getopt.h>
50 #else
51 #include "wsgetopt.h"
52 #endif
53
54 #ifdef _WIN32 /* Needed for console I/O */
55 #include <fcntl.h>
56 #include <conio.h>
57 #endif
58
59 #ifdef HAVE_LIBPORTAUDIO
60 #include <portaudio.h>
61 #endif /* HAVE_LIBPORTAUDIO */
62
63 #include <epan/epan.h>
64 #include <epan/filesystem.h>
65 #include <wsutil/privileges.h>
66 #include <epan/epan_dissect.h>
67 #include <epan/timestamp.h>
68 #include <epan/packet.h>
69 #include <epan/plugins.h>
70 #include <epan/dfilter/dfilter.h>
71 #include <epan/strutil.h>
72 #include <epan/addr_resolv.h>
73 #include <epan/emem.h>
74 #include <epan/ex-opt.h>
75 #include <epan/funnel.h>
76 #include <epan/expert.h>
77 #include <epan/frequency-utils.h>
78 #include <epan/prefs.h>
79 #include <epan/prefs-int.h>
80 #include <epan/tap.h>
81 #include <epan/stat_cmd_args.h>
82 #include <epan/uat.h>
83 #include <epan/emem.h>
84 #include <epan/column.h>
85
86 /* general (not GTK specific) */
87 #include "../file.h"
88 #include "../summary.h"
89 #include "../filters.h"
90 #include "../disabled_protos.h"
91 #include "../color.h"
92 #include "../color_filters.h"
93 #include "../print.h"
94 #include "../simple_dialog.h"
95 #include "../register.h"
96 #include "../ringbuffer.h"
97 #include "../ui_util.h"
98 #include "../util.h"
99 #include "../clopts_common.h"
100 #include "../console_io.h"
101 #include "../cmdarg_err.h"
102 #include "../version_info.h"
103 #include "../merge.h"
104 #include "../alert_box.h"
105 #include "../log.h"
106 #include <wsutil/file_util.h>
107
108 #ifdef HAVE_LIBPCAP
109 #include "../capture_ui_utils.h"
110 #include "../capture-pcap-util.h"
111 #include "../capture_ifinfo.h"
112 #include "../capture.h"
113 #include "../capture_sync.h"
114 #endif
115
116 #ifdef _WIN32
117 #include "../capture-wpcap.h"
118 #include "../capture_wpcap_packet.h"
119 #include <tchar.h> /* Needed for Unicode */
120 #include <commctrl.h>
121 #endif /* _WIN32 */
122
123 /* GTK related */
124 #include "gtk/file_dlg.h"
125 #include "gtk/gtkglobals.h"
126 #include "gtk/color_utils.h"
127 #include "gtk/gui_utils.h"
128 #include "gtk/color_dlg.h"
129 #include "gtk/filter_dlg.h"
130 #include "gtk/uat_gui.h"
131 #include "gtk/u3.h"
132 #include "gtk/main.h"
133 #include "gtk/main_airpcap_toolbar.h"
134 #include "gtk/main_filter_toolbar.h"
135 #include "gtk/menus.h"
136 #include "gtk/main_packet_list.h"
137 #include "gtk/main_statusbar.h"
138 #include "gtk/main_statusbar_private.h"
139 #include "gtk/main_toolbar.h"
140 #include "gtk/main_welcome.h"
141 #include "gtk/drag_and_drop.h"
142 #include "gtk/capture_file_dlg.h"
143 #include "gtk/main_proto_draw.h"
144 #include "gtk/keys.h"
145 #include "gtk/packet_win.h"
146 #include "gtk/stock_icons.h"
147 #include "gtk/find_dlg.h"
148 #include "gtk/recent.h"
149 #include "gtk/follow_tcp.h"
150 #include "gtk/font_utils.h"
151 #include "gtk/about_dlg.h"
152 #include "gtk/help_dlg.h"
153 #include "gtk/decode_as_dlg.h"
154 #include "gtk/webbrowser.h"
155 #include "gtk/capture_dlg.h"
156 #include "gtk/capture_if_dlg.h"
157 #include "gtk/tap_dfilter_dlg.h"
158 #include "gtk/prefs_column.h"
159 #include "gtk/prefs_dlg.h"
160
161 #ifdef HAVE_LIBPCAP
162 #include "../image/wsicon16.xpm"
163 #include "../image/wsicon32.xpm"
164 #include "../image/wsicon48.xpm"
165 #include "../image/wsicon64.xpm"
166 #include "../image/wsiconcap16.xpm"
167 #include "../image/wsiconcap32.xpm"
168 #include "../image/wsiconcap48.xpm"
169 #endif
170
171 #ifdef HAVE_AIRPCAP
172 #include <airpcap.h>
173 #include "airpcap_loader.h"
174 #include "airpcap_dlg.h"
175 #include "airpcap_gui_utils.h"
176 #endif
177
178 #ifdef  HAVE_AIRPDCAP
179 #include <epan/crypt/airpdcap_ws.h>
180 #endif
181
182 #ifdef NEW_PACKET_LIST
183 #include "gtk/new_packet_list.h"
184 #endif
185
186 /*
187  * Files under personal and global preferences directories in which
188  * GTK settings for Wireshark are stored.
189  */
190 #define RC_FILE "gtkrc"
191
192 capture_file cfile;
193
194 /* "exported" main widgets */
195 GtkWidget   *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
196
197 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
198 static GtkWidget   *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
199 static GtkWidget   *main_first_pane, *main_second_pane;
200
201 /* internally used widgets */
202 static GtkWidget   *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
203
204 #ifdef HAVE_AIRPCAP
205 GtkWidget *airpcap_tb;
206 int    airpcap_dll_ret_val = -1;
207 #endif
208
209 GString *comp_info_str, *runtime_info_str;
210 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
211
212 guint  tap_update_timer_id;
213
214 #ifdef _WIN32
215 static gboolean has_console;    /* TRUE if app has console */
216 static void destroy_console(void);
217 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
218 #endif
219 static void console_log_handler(const char *log_domain,
220     GLogLevelFlags log_level, const char *message, gpointer user_data);
221
222 #ifdef HAVE_LIBPCAP
223 capture_options global_capture_opts;
224 #endif
225
226
227 static void create_main_window(gint, gint, gint, e_prefs*);
228 static void show_main_window(gboolean);
229 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
230 static void main_save_window_geometry(GtkWidget *widget);
231
232
233 /* Match selected byte pattern */
234 static void
235 match_selected_cb_do(gpointer data, int action, gchar *text)
236 {
237     GtkWidget  *filter_te;
238     char       *cur_filter, *new_filter;
239
240     if ((!text) || (0 == strlen(text))) {
241         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
242         return;
243     }
244
245     g_assert(data);
246     filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
247     g_assert(filter_te);
248
249     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
250
251     switch (action&MATCH_SELECTED_MASK) {
252
253     case MATCH_SELECTED_REPLACE:
254         new_filter = g_strdup(text);
255         break;
256
257     case MATCH_SELECTED_AND:
258         if ((!cur_filter) || (0 == strlen(cur_filter)))
259             new_filter = g_strdup(text);
260         else
261             new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
262         break;
263
264     case MATCH_SELECTED_OR:
265         if ((!cur_filter) || (0 == strlen(cur_filter)))
266             new_filter = g_strdup(text);
267         else
268             new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
269         break;
270
271     case MATCH_SELECTED_NOT:
272         new_filter = g_strconcat("!(", text, ")", NULL);
273         break;
274
275     case MATCH_SELECTED_AND_NOT:
276         if ((!cur_filter) || (0 == strlen(cur_filter)))
277             new_filter = g_strconcat("!(", text, ")", NULL);
278         else
279             new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
280         break;
281
282     case MATCH_SELECTED_OR_NOT:
283         if ((!cur_filter) || (0 == strlen(cur_filter)))
284             new_filter = g_strconcat("!(", text, ")", NULL);
285         else
286             new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
287         break;
288
289     default:
290         g_assert_not_reached();
291         new_filter = NULL;
292         break;
293     }
294
295     /* Free up the copy we got of the old filter text. */
296     g_free(cur_filter);
297
298     /* Don't change the current display filter if we only want to copy the filter */
299     if (action&MATCH_SELECTED_COPY_ONLY) {
300         GString *gtk_text_str = g_string_new("");
301         g_string_append(gtk_text_str, new_filter);
302         copy_to_clipboard(gtk_text_str);
303         g_string_free(gtk_text_str, TRUE);
304     } else {
305         /* create a new one and set the display filter entry accordingly */
306         gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
307
308         /* Run the display filter so it goes in effect. */
309         if (action&MATCH_SELECTED_APPLY_NOW)
310             main_filter_packets(&cfile, new_filter, FALSE);
311     }
312
313     /* Free up the new filter text. */
314     g_free(new_filter);
315 }
316
317 void
318 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
319 {
320     char *filter = NULL;
321
322     if (cfile.finfo_selected) {
323         filter = proto_construct_match_selected_string(cfile.finfo_selected,
324                                                        cfile.edt);
325         match_selected_cb_do((data ? data : w), action, filter);
326     }
327 }
328
329 void
330 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
331 {
332     char *filter = NULL;
333
334     if (cfile.finfo_selected) {
335         filter = proto_construct_match_selected_string(cfile.finfo_selected,
336                                                        cfile.edt);
337         if ((!filter) || (0 == strlen(filter))) {
338             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
339                 "Could not acquire information to build a filter!\n"
340                 "Try expanding or choosing another item.");
341             return;
342         }
343
344         if (filt_nr==0) {
345             color_display_with_filter(filter);
346         } else {
347             if (filt_nr==255) {
348                 color_filters_reset_tmp();
349             } else {
350                 color_filters_set_tmp(filt_nr,filter, FALSE);
351             }
352             cf_colorize_packets(&cfile);
353         }
354     }
355 }
356
357
358 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
359 {
360     gchar *selected_proto_url;
361     gchar *proto_abbrev = data;
362
363
364     switch(btn) {
365     case(ESD_BTN_OK):
366         if (cfile.finfo_selected) {
367             /* open wiki page using the protocol abbreviation */
368             selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
369             browser_open_url(selected_proto_url);
370             g_free(selected_proto_url);
371         }
372         break;
373     case(ESD_BTN_CANCEL):
374         break;
375     default:
376         g_assert_not_reached();
377     }
378 }
379
380
381 void
382 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
383 {
384     int field_id;
385     const gchar *proto_abbrev;
386     gpointer  dialog;
387
388
389     if (cfile.finfo_selected) {
390         /* convert selected field to protocol abbreviation */
391         /* XXX - could this conversion be simplified? */
392         field_id = cfile.finfo_selected->hfinfo->id;
393         /* if the selected field isn't a protocol, get it's parent */
394         if(!proto_registrar_is_protocol(field_id)) {
395             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
396         }
397
398         proto_abbrev = proto_registrar_get_abbrev(field_id);
399
400         if (!proto_is_private(field_id)) {
401             /* ask the user if the wiki page really should be opened */
402             dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
403                     "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
404                     "\n"
405                     "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
406                     "\n"
407                     "The Wireshark Wiki is a collaborative approach to provide information "
408                     "about Wireshark in several ways (not limited to protocol specifics).\n"
409                     "\n"
410                     "This Wiki is new, so the page of the selected protocol "
411                     "may not exist and/or may not contain valuable information.\n"
412                     "\n"
413                     "As everyone can edit the Wiki and add new content (or extend existing), "
414                     "you are encouraged to add information if you can.\n"
415                     "\n"
416                     "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
417                     "\n"
418                     "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
419                     "which will save you a lot of editing and will give a consistent look over the pages.",
420                     simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
421             simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
422         } else {
423             /* appologize to the user that the wiki page cannot be opened */
424             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
425                     "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
426                     "\n"
427                     "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
428                     "\n"
429                     "Since this is a private protocol, such information is not available in "
430                     "a public wiki. Therefore this wiki entry is blocked.\n"
431                     "\n"
432                     "Sorry for the inconvenience.\n",
433                     simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
434         }
435     }
436 }
437
438 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
439 {
440     gchar *selected_proto_url;
441     gchar *proto_abbrev = data;
442
443     switch(btn) {
444     case(ESD_BTN_OK):
445         if (cfile.finfo_selected) {
446             /* open reference page using the protocol abbreviation */
447             selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
448             browser_open_url(selected_proto_url);
449             g_free(selected_proto_url);
450         }
451         break;
452     case(ESD_BTN_CANCEL):
453         break;
454     default:
455         g_assert_not_reached();
456     }
457 }
458
459 void
460 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
461 {
462     int field_id;
463     const gchar *proto_abbrev;
464     gpointer  dialog;
465
466
467     if (cfile.finfo_selected) {
468         /* convert selected field to protocol abbreviation */
469         /* XXX - could this conversion be simplified? */
470         field_id = cfile.finfo_selected->hfinfo->id;
471         /* if the selected field isn't a protocol, get it's parent */
472         if(!proto_registrar_is_protocol(field_id)) {
473             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
474         }
475
476         proto_abbrev = proto_registrar_get_abbrev(field_id);
477
478         if (!proto_is_private(field_id)) {
479             /* ask the user if the wiki page really should be opened */
480             dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
481                     "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
482                     "\n"
483                     "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
484                     "\n",
485                     simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
486             simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
487         } else {
488             /* appologize to the user that the wiki page cannot be opened */
489             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
490                     "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
491                     "\n"
492                     "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
493                     "\n"
494                     "Since this is a private protocol, such information is not available on "
495                     "a public website. Therefore this filter entry is blocked.\n"
496                     "\n"
497                     "Sorry for the inconvenience.\n",
498                     simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
499         }
500     }
501 }
502
503 static gboolean
504 is_address_column (gint column)
505 {
506   if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
507        (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
508        (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
509        (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
510       strlen(cfile.cinfo.col_expr.col_expr_val[column]))
511   {
512     return TRUE;
513   }
514
515   return FALSE;
516 }
517
518 GList *
519 get_ip_address_list_from_packet_list_row(gpointer data)
520 {
521     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
522     gint    column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
523     gint    col;
524     frame_data *fdata;
525     GList      *addr_list = NULL;
526     int         err;
527     gchar       *err_info;
528
529 #ifdef NEW_PACKET_LIST
530     fdata = (frame_data *) new_packet_list_get_row_data(row);
531 #else
532     fdata = (frame_data *) packet_list_get_row_data(row);
533 #endif
534
535     if (fdata != NULL) {
536         epan_dissect_t edt;
537
538         if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
539                    cfile.pd, fdata->cap_len, &err, &err_info))
540         {
541             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
542                       cf_read_error_message(err, err_info), cfile.filename);
543             return NULL;
544         }
545
546         epan_dissect_init(&edt, FALSE, FALSE);
547         col_custom_prime_edt(&edt, &cfile.cinfo);
548
549         epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
550         epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
551
552         /* First check selected column */
553         if (is_address_column (column)) {
554           addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
555         }
556
557         for (col = 0; col < cfile.cinfo.num_cols; col++) {
558           /* Then check all columns except the selected */
559           if ((col != column) && (is_address_column (col))) {
560             addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
561           }
562         }
563
564         epan_dissect_cleanup(&edt);
565     }
566
567     return addr_list;
568 }
569
570 static gchar *
571 get_filter_from_packet_list_row_and_column(gpointer data)
572 {
573     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
574     gint    column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
575     frame_data *fdata;
576     gchar      *buf=NULL;
577     int         err;
578     gchar       *err_info;
579
580 #ifdef NEW_PACKET_LIST
581     fdata = (frame_data *) new_packet_list_get_row_data(row);
582 #else
583     fdata = (frame_data *) packet_list_get_row_data(row);
584 #endif
585
586     if (fdata != NULL) {
587         epan_dissect_t edt;
588
589         if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
590                    cfile.pd, fdata->cap_len, &err, &err_info)) {
591             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
592                       cf_read_error_message(err, err_info), cfile.filename);
593             return NULL;
594         }
595         /* proto tree, visible. We need a proto tree if there's custom columns */
596         epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
597         col_custom_prime_edt(&edt, &cfile.cinfo);
598
599         epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
600                  &cfile.cinfo);
601         epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
602
603         if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
604             strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
605             /* leak a little but safer than ep_ here */
606             if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
607                 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
608                 if (hfi->parent == -1) {
609                     /* Protocol only */
610                     buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
611                 } else if (hfi->type == FT_STRING) {
612                     /* Custom string, add quotes */
613                     buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
614                                            cfile.cinfo.col_expr.col_expr_val[column]);
615                 }
616             }
617             if (buf == NULL) {
618                 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
619                                        cfile.cinfo.col_expr.col_expr_val[column]);
620             }
621         }
622
623         epan_dissect_cleanup(&edt);
624     }
625
626     return buf;
627 }
628
629 void
630 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
631 {
632     match_selected_cb_do(data,
633         action,
634         get_filter_from_packet_list_row_and_column(data));
635 }
636
637 /* This function allows users to right click in the details window and copy the text
638  * information to the operating systems clipboard.
639  *
640  * We first check to see if a string representation is setup in the tree and then
641  * read the string. If not available then we try to grab the value. If all else
642  * fails we display a message to the user to indicate the copy could not be completed.
643  */
644 void
645 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
646 {
647     GString *gtk_text_str = g_string_new("");
648     char labelstring[256];
649     char *stringpointer = labelstring;
650
651     switch(action)
652     {
653     case COPY_SELECTED_DESCRIPTION:
654         if (cfile.finfo_selected->rep->representation != 0) {
655             g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
656         }
657         break;
658     case COPY_SELECTED_FIELDNAME:
659         if (cfile.finfo_selected->hfinfo->abbrev != 0) {
660             g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
661         }
662         break;
663     case COPY_SELECTED_VALUE:
664         if (cfile.edt !=0 ) {
665             g_string_append(gtk_text_str,
666                     get_node_field_value(cfile.finfo_selected, cfile.edt));
667         }
668         break;
669     default:
670         break;
671     }
672
673     if (gtk_text_str->len == 0) {
674         /* If no representation then... Try to read the value */
675         proto_item_fill_label(cfile.finfo_selected, stringpointer);
676         g_string_append(gtk_text_str, stringpointer);
677     }
678
679     if (gtk_text_str->len == 0) {
680         /* Could not get item so display error msg */
681         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
682     } else {
683         /* Copy string to clipboard */
684         copy_to_clipboard(gtk_text_str);
685     }
686     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
687 }
688
689
690 /* mark as reference time frame */
691 static void
692 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
693   if (row == -1)
694     return;
695   if (set) {
696     frame->flags.ref_time=1;
697   } else {
698     frame->flags.ref_time=0;
699   }
700   cf_reftime_packets(&cfile);
701 #ifdef NEW_PACKET_LIST
702   new_packet_list_queue_draw();
703 #endif
704 }
705
706
707 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
708 {
709     switch(btn) {
710     case(ESD_BTN_YES):
711         timestamp_set_type(TS_RELATIVE);
712         recent.gui_time_format  = TS_RELATIVE;
713 #ifdef NEW_PACKET_LIST
714                 cf_timestamp_auto_precision(&cfile);
715                 new_packet_list_queue_draw();
716 #else
717         cf_change_time_formats(&cfile);
718 #endif
719         break;
720     case(ESD_BTN_NO):
721         break;
722     default:
723         g_assert_not_reached();
724     }
725
726     if (cfile.current_frame) {
727       set_frame_reftime(!cfile.current_frame->flags.ref_time,
728                         cfile.current_frame, cfile.current_row);
729     }
730 }
731
732
733 void
734 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
735 {
736   static GtkWidget *reftime_dialog = NULL;
737
738   switch(action){
739   case REFTIME_TOGGLE:
740     if (cfile.current_frame) {
741         if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
742             reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
743                 "%sSwitch to the appropriate Time Display Format?%s\n\n"
744                 "Time References don't work well with the currently selected Time Display Format.\n\n"
745                 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
746                 simple_dialog_primary_start(), simple_dialog_primary_end());
747             simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
748         } else {
749             set_frame_reftime(!cfile.current_frame->flags.ref_time,
750                               cfile.current_frame, cfile.current_row);
751         }
752     }
753     break;
754   case REFTIME_FIND_NEXT:
755     find_previous_next_frame_with_filter("frame.ref_time", FALSE);
756     break;
757   case REFTIME_FIND_PREV:
758     find_previous_next_frame_with_filter("frame.ref_time", TRUE);
759     break;
760   }
761 }
762
763 void
764 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
765 {
766     find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
767 }
768
769 void
770 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
771 {
772     find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
773 }
774
775 static void
776 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
777 {
778     field_info   *finfo;
779     gchar        *help_str = NULL;
780     gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
781                                           N < 4294967296 */
782     gboolean      has_blurb = FALSE;
783     guint         length = 0, byte_len;
784     GtkWidget    *byte_view;
785     const guint8 *byte_data;
786     gint          finfo_length;
787     GtkTreeModel *model;
788     GtkTreeIter   iter;
789
790     /* if nothing is selected */
791     if (!gtk_tree_selection_get_selected(sel, &model, &iter))
792     {
793         /*
794          * Which byte view is displaying the current protocol tree
795          * row's data?
796          */
797         byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
798         if (byte_view == NULL)
799             return;     /* none */
800
801         byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
802         if (byte_data == NULL)
803             return;     /* none */
804
805         cf_unselect_field(&cfile);
806         packet_hex_print(byte_view, byte_data,
807                          cfile.current_frame, NULL, byte_len);
808         return;
809     }
810     gtk_tree_model_get(model, &iter, 1, &finfo, -1);
811     if (!finfo) return;
812
813     set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
814
815     byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
816     byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
817     g_assert(byte_data != NULL);
818
819     cfile.finfo_selected = finfo;
820     set_menus_for_selected_tree_row(&cfile);
821
822     if (finfo->hfinfo) {
823         if (finfo->hfinfo->blurb != NULL &&
824             finfo->hfinfo->blurb[0] != '\0') {
825             has_blurb = TRUE;
826             length = (guint) strlen(finfo->hfinfo->blurb);
827         } else {
828             length = (guint) strlen(finfo->hfinfo->name);
829         }
830         finfo_length = finfo->length + finfo->appendix_length;
831
832         if (finfo_length == 0) {
833             len_str[0] = '\0';
834         } else if (finfo_length == 1) {
835             g_strlcpy (len_str, ", 1 byte", sizeof len_str);
836         } else {
837             g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
838         }
839         statusbar_pop_field_msg();      /* get rid of current help msg */
840         if (length) {
841             help_str = g_strdup_printf(" %s (%s)%s",
842                     (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
843                     finfo->hfinfo->abbrev, len_str);
844             statusbar_push_field_msg(help_str);
845             g_free(help_str);
846         } else {
847             /*
848              * Don't show anything if the field name is zero-length;
849              * the pseudo-field for "proto_tree_add_text()" is such
850              * a field, and we don't want "Text (text)" showing up
851              * on the status line if you've selected such a field.
852              *
853              * XXX - there are zero-length fields for which we *do*
854              * want to show the field name.
855              *
856              * XXX - perhaps the name and abbrev field should be null
857              * pointers rather than null strings for that pseudo-field,
858              * but we'd have to add checks for null pointers in some
859              * places if we did that.
860              *
861              * Or perhaps protocol tree items added with
862              * "proto_tree_add_text()" should have -1 as the field index,
863              * with no pseudo-field being used, but that might also
864              * require special checks for -1 to be added.
865              */
866             statusbar_push_field_msg("");
867         }
868     }
869     packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
870                      byte_len);
871 }
872
873 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
874   if (cfile.edt->tree)
875     collapse_all_tree(cfile.edt->tree, tree_view_gbl);
876 }
877
878 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
879   if (cfile.edt->tree)
880     expand_all_tree(cfile.edt->tree, tree_view_gbl);
881 }
882
883 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
884 {
885   if (cfile.finfo_selected) {
886     column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
887                             cfile.finfo_selected->hfinfo->abbrev);
888     /* Recreate the packet list according to new preferences */
889 #ifdef NEW_PACKET_LIST
890     new_packet_list_recreate ();
891 #else
892     packet_list_recreate ();
893 #endif
894     if (!prefs.gui_use_pref_save) {
895       prefs_main_write();
896     }
897     cfile.cinfo.columns_changed = FALSE; /* Reset value */
898   }
899 }
900
901 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
902   GtkTreePath  *path;
903
904   path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
905   if(path) {
906     /* the mouse position is at an entry, expand that one */
907     gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
908     gtk_tree_path_free(path);
909   }
910 }
911
912 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
913   if (cfile.edt->tree) {
914     guint32 tmp = g_resolv_flags;
915     g_resolv_flags = RESOLV_ALL;
916     proto_tree_draw(cfile.edt->tree, tree_view_gbl);
917     g_resolv_flags = tmp;
918   }
919 }
920
921 static void
922 main_set_for_capture_file(gboolean have_capture_file_in)
923 {
924     have_capture_file = have_capture_file_in;
925
926     main_widgets_show_or_hide();
927 }
928
929 gboolean
930 main_do_quit(void)
931 {
932         /* get the current geometry, before writing it to disk */
933         main_save_window_geometry(top_level);
934
935         /* write user's recent file to disk
936          * It is no problem to write this file, even if we do not quit */
937         write_profile_recent();
938         write_recent();
939
940         /* XXX - should we check whether the capture file is an
941            unsaved temporary file for a live capture and, if so,
942            pop up a "do you want to exit without saving the capture
943            file?" dialog, and then just return, leaving said dialog
944            box to forcibly quit if the user clicks "OK"?
945
946            If so, note that this should be done in a subroutine that
947            returns TRUE if we do so, and FALSE otherwise, and if it
948            returns TRUE we should return TRUE without nuking anything.
949
950            Note that, if we do that, we might also want to check if
951            an "Update list of packets in real time" capture is in
952            progress and, if so, ask whether they want to terminate
953            the capture and discard it, and return TRUE, before nuking
954            any child capture, if they say they don't want to do so. */
955
956 #ifdef HAVE_LIBPCAP
957         /* Nuke any child capture in progress. */
958         capture_kill_child(&global_capture_opts);
959 #endif
960
961         /* Are we in the middle of reading a capture? */
962         if (cfile.state == FILE_READ_IN_PROGRESS) {
963                 /* Yes, so we can't just close the file and quit, as
964                    that may yank the rug out from under the read in
965                    progress; instead, just set the state to
966                    "FILE_READ_ABORTED" and return - the code doing the read
967                    will check for that and, if it sees that, will clean
968                    up and quit. */
969                 cfile.state = FILE_READ_ABORTED;
970
971                 /* Say that the window should *not* be deleted;
972                    that'll be done by the code that cleans up. */
973                 return TRUE;
974         } else {
975                 /* Close any capture file we have open; on some OSes, you
976                    can't unlink a temporary capture file if you have it
977                    open.
978                    "cf_close()" will unlink it after closing it if
979                    it's a temporary file.
980
981                    We do this here, rather than after the main loop returns,
982                    as, after the main loop returns, the main window may have
983                    been destroyed (if this is called due to a "destroy"
984                    even on the main window rather than due to the user
985                    selecting a menu item), and there may be a crash
986                    or other problem when "cf_close()" tries to
987                    clean up stuff in the main window.
988
989                    XXX - is there a better place to put this?
990                    Or should we have a routine that *just* closes the
991                    capture file, and doesn't do anything with the UI,
992                    which we'd call here, and another routine that
993                    calls that routine and also cleans up the UI, which
994                    we'd call elsewhere? */
995                 cf_close(&cfile);
996
997                 /* Exit by leaving the main loop, so that any quit functions
998                    we registered get called. */
999                 gtk_main_quit();
1000
1001                 /* Say that the window should be deleted. */
1002                 return FALSE;
1003         }
1004 }
1005
1006 static gboolean
1007 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1008 {
1009   gpointer dialog;
1010
1011   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1012     gtk_window_present(GTK_WINDOW(top_level));
1013     /* user didn't saved his current file, ask him */
1014     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1015                 "%sSave capture file before program quit?%s\n\n"
1016                 "If you quit the program without saving, your capture data will be discarded.",
1017                 simple_dialog_primary_start(), simple_dialog_primary_end());
1018     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1019     return TRUE;
1020   } else {
1021     /* unchanged file, just exit */
1022     /* "main_do_quit()" indicates whether the main window should be deleted. */
1023     return main_do_quit();
1024   }
1025 }
1026
1027
1028 static void
1029 main_pane_load_window_geometry(void)
1030 {
1031     if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1032         gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1033     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1034         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1035     }
1036 }
1037
1038
1039 static void
1040 main_load_window_geometry(GtkWidget *widget)
1041 {
1042     window_geometry_t geom;
1043
1044     geom.set_pos        = prefs.gui_geometry_save_position;
1045     geom.x              = recent.gui_geometry_main_x;
1046     geom.y              = recent.gui_geometry_main_y;
1047     geom.set_size       = prefs.gui_geometry_save_size;
1048     if (recent.gui_geometry_main_width > 0 &&
1049         recent.gui_geometry_main_height > 0) {
1050         geom.width          = recent.gui_geometry_main_width;
1051         geom.height         = recent.gui_geometry_main_height;
1052         geom.set_maximized  = prefs.gui_geometry_save_maximized;
1053     } else {
1054         /* We assume this means the width and height weren't set in
1055            the "recent" file (or that there is no "recent" file),
1056            and weren't set to a default value, so we don't set the
1057            size.  (The "recent" file code rejects non-positive width
1058            and height values.) */
1059        geom.set_size = FALSE;
1060     }
1061     geom.maximized      = recent.gui_geometry_main_maximized;
1062
1063     window_set_geometry(widget, &geom);
1064
1065     main_pane_load_window_geometry();
1066     statusbar_load_window_geometry();
1067 }
1068
1069
1070 static void
1071 main_save_window_geometry(GtkWidget *widget)
1072 {
1073     window_geometry_t geom;
1074
1075     window_get_geometry(widget, &geom);
1076
1077     if (prefs.gui_geometry_save_position) {
1078         recent.gui_geometry_main_x = geom.x;
1079         recent.gui_geometry_main_y = geom.y;
1080     }
1081
1082     if (prefs.gui_geometry_save_size) {
1083         recent.gui_geometry_main_width  = geom.width;
1084         recent.gui_geometry_main_height = geom.height;
1085     }
1086
1087     if(prefs.gui_geometry_save_maximized) {
1088         recent.gui_geometry_main_maximized = geom.maximized;
1089     }
1090
1091     recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
1092     recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
1093     statusbar_save_window_geometry();
1094 }
1095
1096 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1097 {
1098     switch(btn) {
1099     case(ESD_BTN_SAVE):
1100         /* save file first */
1101         file_save_as_cmd(after_save_exit, NULL);
1102         break;
1103     case(ESD_BTN_QUIT_DONT_SAVE):
1104         main_do_quit();
1105         break;
1106     case(ESD_BTN_CANCEL):
1107         break;
1108     default:
1109         g_assert_not_reached();
1110     }
1111 }
1112
1113 void
1114 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1115 {
1116   gpointer dialog;
1117
1118   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1119     /* user didn't saved his current file, ask him */
1120     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1121                 "%sSave capture file before program quit?%s\n\n"
1122                 "If you quit the program without saving, your capture data will be discarded.",
1123                 simple_dialog_primary_start(), simple_dialog_primary_end());
1124     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1125   } else {
1126     /* unchanged file, just exit */
1127     main_do_quit();
1128   }
1129 }
1130
1131 static void
1132 print_usage(gboolean print_ver) {
1133
1134   FILE *output;
1135
1136 #ifdef _WIN32
1137   create_console();
1138 #endif
1139
1140   if (print_ver) {
1141     output = stdout;
1142     fprintf(output, "Wireshark " VERSION "%s\n"
1143         "Interactively dump and analyze network traffic.\n"
1144         "See http://www.wireshark.org for more information.\n"
1145         "\n"
1146         "%s",
1147         wireshark_svnversion, get_copyright_info());
1148   } else {
1149     output = stderr;
1150   }
1151   fprintf(output, "\n");
1152   fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1153   fprintf(output, "\n");
1154
1155 #ifdef HAVE_LIBPCAP
1156   fprintf(output, "Capture interface:\n");
1157   fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
1158   fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
1159   fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
1160   fprintf(output, "  -p                       don't capture in promiscuous mode\n");
1161   fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
1162   fprintf(output, "  -Q                       quit Wireshark after capturing\n");
1163   fprintf(output, "  -S                       update packet display when new packets are captured\n");
1164   fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
1165 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1166   fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
1167 #endif
1168   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
1169   fprintf(output, "  -D                       print list of interfaces and exit\n");
1170   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
1171   fprintf(output, "\n");
1172   fprintf(output, "Capture stop conditions:\n");
1173   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
1174   fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
1175   fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
1176   fprintf(output, "                              files:NUM - stop after NUM files\n");
1177   /*fprintf(output, "\n");*/
1178   fprintf(output, "Capture output:\n");
1179   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1180   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
1181   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
1182 #endif  /* HAVE_LIBPCAP */
1183
1184   /*fprintf(output, "\n");*/
1185   fprintf(output, "Input file:\n");
1186   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
1187
1188   fprintf(output, "\n");
1189   fprintf(output, "Processing:\n");
1190   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
1191   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
1192   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
1193
1194   fprintf(output, "\n");
1195   fprintf(output, "User interface:\n");
1196   fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
1197   fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
1198   fprintf(output, "  -J <jump filter>         jump to the first packet matching the (display) filter\n");
1199   fprintf(output, "  -j                       search backwards for a matching packet after \"-J\"\n");
1200   fprintf(output, "  -m <font>                set the font name used for most text\n");
1201   fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
1202   fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
1203   fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
1204   fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
1205
1206   fprintf(output, "\n");
1207   fprintf(output, "Output:\n");
1208   fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
1209
1210   fprintf(output, "\n");
1211   fprintf(output, "Miscellaneous:\n");
1212   fprintf(output, "  -h                       display this help and exit\n");
1213   fprintf(output, "  -v                       display version info and exit\n");
1214   fprintf(output, "  -P <key>:<path>          persconf:path - personal configuration files\n");
1215   fprintf(output, "                           persdata:path - personal data files\n");
1216   fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
1217   fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
1218 #ifndef _WIN32
1219   fprintf(output, "  --display=DISPLAY        X display to use\n");
1220 #endif
1221
1222 #ifdef _WIN32
1223   destroy_console();
1224 #endif
1225 }
1226
1227 static void
1228 show_version(void)
1229 {
1230 #ifdef _WIN32
1231   create_console();
1232 #endif
1233
1234   printf(PACKAGE " " VERSION "%s\n"
1235          "\n"
1236          "%s"
1237          "\n"
1238          "%s"
1239          "\n"
1240          "%s",
1241       wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1242       runtime_info_str->str);
1243
1244 #ifdef _WIN32
1245   destroy_console();
1246 #endif
1247 }
1248
1249 /*
1250  * Print to the standard error.  On Windows, create a console for the
1251  * standard error to show up on, if necessary.
1252  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1253  * terminal isn't the standard error?
1254  */
1255 void
1256 vfprintf_stderr(const char *fmt, va_list ap)
1257 {
1258 #ifdef _WIN32
1259   create_console();
1260 #endif
1261   vfprintf(stderr, fmt, ap);
1262 }
1263
1264 void
1265 fprintf_stderr(const char *fmt, ...)
1266 {
1267   va_list ap;
1268
1269   va_start(ap, fmt);
1270   vfprintf_stderr(fmt, ap);
1271   va_end(ap);
1272 }
1273
1274 /*
1275  * Report an error in command-line arguments.
1276  * Creates a console on Windows.
1277  */
1278 void
1279 cmdarg_err(const char *fmt, ...)
1280 {
1281   va_list ap;
1282
1283   fprintf_stderr("wireshark: ");
1284   va_start(ap, fmt);
1285   vfprintf_stderr(fmt, ap);
1286   va_end(ap);
1287   fprintf_stderr("\n");
1288 }
1289
1290 /*
1291  * Report additional information for an error in command-line arguments.
1292  * Creates a console on Windows.
1293  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1294  * terminal isn't the standard error?
1295  */
1296 void
1297 cmdarg_err_cont(const char *fmt, ...)
1298 {
1299   va_list ap;
1300
1301   va_start(ap, fmt);
1302   vfprintf_stderr(fmt, ap);
1303   fprintf_stderr("\n");
1304   va_end(ap);
1305 }
1306
1307 #if defined(_WIN32) || ! defined USE_THREADS
1308 /*
1309    Once every 3 seconds we get a callback here which we use to update
1310    the tap extensions. Since Gtk1 is single threaded we dont have to
1311    worry about any locking or critical regions.
1312  */
1313 static gboolean
1314 tap_update_cb(gpointer data _U_)
1315 {
1316         draw_tap_listeners(FALSE);
1317         return TRUE;
1318 }
1319
1320 /* Restart the tap update display timer with new configured interval */
1321 void reset_tap_update_timer(void)
1322 {
1323     g_source_remove(tap_update_timer_id);
1324     tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1325 }
1326
1327 #else
1328
1329 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1330    use threads all update_thread_mutex can be dropped and protect/unprotect
1331    would just be empty functions.
1332
1333    This allows gtk2-rpcstat.c and friends to be copied unmodified to
1334    gtk1-wireshark and it will just work.
1335  */
1336 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1337 gpointer
1338 update_thread(gpointer data _U_)
1339 {
1340     while(1){
1341         GTimeVal tv1, tv2;
1342         g_get_current_time(&tv1);
1343         g_static_mutex_lock(&update_thread_mutex);
1344         gdk_threads_enter();
1345         draw_tap_listeners(FALSE);
1346         gdk_threads_leave();
1347         g_static_mutex_unlock(&update_thread_mutex);
1348         g_thread_yield();
1349         g_get_current_time(&tv2);
1350
1351         /* Assuming it took less than configured time to update tap listeners... */
1352         if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1353             (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1354             /* Wait for remainder of configured time */
1355             g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1356                      (tv2.tv_sec * 1000000 + tv2.tv_usec));
1357         }
1358
1359         return NULL;
1360 }
1361 #endif
1362 void
1363 protect_thread_critical_region(void)
1364 {
1365 #if !defined(_WIN32) && defined USE_THREADS
1366     g_static_mutex_lock(&update_thread_mutex);
1367 #endif
1368 }
1369 void
1370 unprotect_thread_critical_region(void)
1371 {
1372 #if !defined(_WIN32) && defined USE_THREADS
1373     g_static_mutex_unlock(&update_thread_mutex);
1374 #endif
1375 }
1376
1377 /*
1378  * Periodically process outstanding hostname lookups. If we have new items,
1379  * redraw the packet list and tree view.
1380  */
1381
1382 static gboolean
1383 resolv_update_cb(gpointer data _U_)
1384 {
1385   /* Anything new show up? */
1386   if (host_name_lookup_process(NULL)) {
1387     if (pkt_scrollw->window)
1388         gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1389     if (tv_scrollw->window)
1390         gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1391   }
1392
1393   /* Always check. Even if we don't do async lookups we could still get
1394      passive updates, e.g. from DNS packets. */
1395   return TRUE;
1396 }
1397
1398
1399 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1400 static void
1401 set_display_filename(capture_file *cf)
1402 {
1403   gchar       *win_name;
1404
1405   if (!cf->is_tempfile && cf->filename) {
1406     /* Add this filename to the list of recent files in the "Recent Files" submenu */
1407     add_menu_recent_capture_file(cf->filename);
1408   }
1409
1410   /* window title */
1411   win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1412   set_main_window_name(win_name);
1413   g_free(win_name);
1414 }
1415
1416 GtkWidget           *close_dlg = NULL;
1417
1418 static void
1419 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1420 {
1421     recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1422 }
1423
1424 #ifdef _WIN32
1425 static void
1426 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1427 {
1428     recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1429 }
1430 #endif
1431
1432 static void
1433 main_cf_cb_file_closing(capture_file *cf)
1434 {
1435
1436     /* if we have more than 10000 packets, show a splash screen while closing */
1437     /* XXX - don't know a better way to decide whether to show or not,
1438      * as most of the time is spend in a single eth_clist_clear function,
1439      * so we can't use a progress bar here! */
1440     if(cf->count > 10000) {
1441         close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1442                                   "%sClosing file!%s\n\nPlease wait ...",
1443                                   simple_dialog_primary_start(),
1444                                   simple_dialog_primary_end());
1445         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1446     }
1447
1448     /* Destroy all windows, which refer to the
1449        capture file we're closing. */
1450     destroy_packet_wins();
1451     file_save_as_destroy();
1452
1453     /* Restore the standard title bar message. */
1454     set_main_window_name("The Wireshark Network Analyzer");
1455
1456     /* Disable all menu items that make sense only if you have a capture. */
1457     set_menus_for_capture_file(NULL);
1458     set_menus_for_captured_packets(FALSE);
1459     set_menus_for_selected_packet(cf);
1460     set_menus_for_capture_in_progress(FALSE);
1461     set_capture_if_dialog_for_capture_in_progress(FALSE);
1462     set_menus_for_selected_tree_row(cf);
1463
1464     /* Set up main window for no capture file. */
1465     main_set_for_capture_file(FALSE);
1466
1467     main_window_update();
1468 }
1469
1470 static void
1471 main_cf_cb_file_closed(capture_file *cf _U_)
1472 {
1473   if(close_dlg != NULL) {
1474     splash_destroy(close_dlg);
1475     close_dlg = NULL;
1476   }
1477 }
1478
1479
1480 static void
1481 main_cf_cb_file_read_started(capture_file *cf _U_)
1482 {
1483   tap_dfilter_dlg_update();
1484
1485   /* Set up main window for a capture file. */
1486   main_set_for_capture_file(TRUE);
1487 }
1488
1489 static void
1490 main_cf_cb_file_read_finished(capture_file *cf)
1491 {
1492     set_display_filename(cf);
1493
1494     /* Enable menu items that make sense if you have a capture file you've
1495        finished reading. */
1496     set_menus_for_capture_file(cf);
1497
1498     /* Enable menu items that make sense if you have some captured packets. */
1499     set_menus_for_captured_packets(TRUE);
1500 }
1501
1502 #ifdef HAVE_LIBPCAP
1503 static GList *icon_list_create(
1504     const char **icon16_xpm,
1505     const char **icon32_xpm,
1506     const char **icon48_xpm,
1507     const char **icon64_xpm)
1508 {
1509   GList *icon_list = NULL;
1510   GdkPixbuf * pixbuf16;
1511   GdkPixbuf * pixbuf32;
1512   GdkPixbuf * pixbuf48;
1513   GdkPixbuf * pixbuf64;
1514
1515
1516   if(icon16_xpm != NULL) {
1517       pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1518       g_assert(pixbuf16);
1519       icon_list = g_list_append(icon_list, pixbuf16);
1520   }
1521
1522   if(icon32_xpm != NULL) {
1523       pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1524       g_assert(pixbuf32);
1525       icon_list = g_list_append(icon_list, pixbuf32);
1526   }
1527
1528   if(icon48_xpm != NULL) {
1529       pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1530       g_assert(pixbuf48);
1531       icon_list = g_list_append(icon_list, pixbuf48);
1532   }
1533
1534   if(icon64_xpm != NULL) {
1535       pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1536       g_assert(pixbuf64);
1537       icon_list = g_list_append(icon_list, pixbuf64);
1538   }
1539
1540   return icon_list;
1541 }
1542
1543 static void
1544 main_capture_set_main_window_title(capture_options *capture_opts)
1545 {
1546     GString *title = g_string_new("");
1547
1548     g_string_append(title, "Capturing ");
1549     if(capture_opts->iface) {
1550         g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1551     }
1552     g_string_append(title, "- Wireshark");
1553
1554     set_main_window_name(title->str);
1555     g_string_free(title, TRUE);
1556 }
1557
1558 static void
1559 main_capture_cb_capture_prepared(capture_options *capture_opts)
1560 {
1561     static GList *icon_list = NULL;
1562
1563     main_capture_set_main_window_title(capture_opts);
1564
1565     if(icon_list == NULL) {
1566         icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1567     }
1568     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1569
1570     /* Disable menu items that make no sense if you're currently running
1571        a capture. */
1572     set_menus_for_capture_in_progress(TRUE);
1573     set_capture_if_dialog_for_capture_in_progress(TRUE);
1574
1575     /* Don't set up main window for a capture file. */
1576     main_set_for_capture_file(FALSE);
1577 }
1578
1579 static void
1580 main_capture_cb_capture_update_started(capture_options *capture_opts)
1581 {
1582     /* We've done this in "prepared" above, but it will be cleared while
1583        switching to the next multiple file. */
1584     main_capture_set_main_window_title(capture_opts);
1585
1586     set_menus_for_capture_in_progress(TRUE);
1587     set_capture_if_dialog_for_capture_in_progress(TRUE);
1588
1589     /* Enable menu items that make sense if you have some captured
1590        packets (yes, I know, we don't have any *yet*). */
1591     set_menus_for_captured_packets(TRUE);
1592
1593     /* Set up main window for a capture file. */
1594     main_set_for_capture_file(TRUE);
1595 }
1596
1597 static void
1598 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1599 {
1600     capture_file *cf = capture_opts->cf;
1601     static GList *icon_list = NULL;
1602
1603     set_display_filename(cf);
1604
1605     /* Enable menu items that make sense if you're not currently running
1606      a capture. */
1607     set_menus_for_capture_in_progress(FALSE);
1608     set_capture_if_dialog_for_capture_in_progress(FALSE);
1609
1610     /* Enable menu items that make sense if you have a capture file
1611        you've finished reading. */
1612     set_menus_for_capture_file(cf);
1613
1614     /* Set up main window for a capture file. */
1615     main_set_for_capture_file(TRUE);
1616
1617     if(icon_list == NULL) {
1618         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1619     }
1620     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1621
1622     if(global_capture_opts.quit_after_cap) {
1623         /* command line asked us to quit after the capture */
1624         /* don't pop up a dialog to ask for unsaved files etc. */
1625         main_do_quit();
1626     }
1627 }
1628
1629 static void
1630 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1631 {
1632     /* Don't set up main window for a capture file. */
1633     main_set_for_capture_file(FALSE);
1634 }
1635
1636 static void
1637 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1638 {
1639 #if 0
1640     capture_file *cf = capture_opts->cf;
1641 #endif
1642     static GList *icon_list = NULL;
1643
1644     /*set_display_filename(cf);*/
1645
1646     /* Enable menu items that make sense if you're not currently running
1647      a capture. */
1648     set_menus_for_capture_in_progress(FALSE);
1649     set_capture_if_dialog_for_capture_in_progress(FALSE);
1650
1651     /* Restore the standard title bar message */
1652     /* (just in case we have trouble opening the capture file). */
1653     set_main_window_name("The Wireshark Network Analyzer");
1654
1655     if(icon_list == NULL) {
1656         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1657     }
1658     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1659
1660     /* We don't have loaded the capture file, this will be done later.
1661      * For now we still have simply a blank screen. */
1662
1663     if(global_capture_opts.quit_after_cap) {
1664         /* command line asked us to quit after the capture */
1665         /* don't pop up a dialog to ask for unsaved files etc. */
1666         main_do_quit();
1667     }
1668 }
1669
1670 #endif  /* HAVE_LIBPCAP */
1671
1672 static void
1673 main_cf_cb_packet_selected(gpointer data)
1674 {
1675     capture_file *cf = data;
1676
1677     /* Display the GUI protocol tree and packet bytes.
1678       XXX - why do we dump core if we call "proto_tree_draw()"
1679       before calling "add_byte_views()"? */
1680     add_main_byte_views(cf->edt);
1681     main_proto_tree_draw(cf->edt->tree);
1682
1683     /* The user is searching for a string in the data or a hex value,
1684      * highlight the field that is found in the tree and hex displays. */
1685     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1686         highlight_field(cf->edt->tvb, cfile.search_pos,
1687                         (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1688         cfile.search_pos = 0; /* Reset the position */
1689     }
1690
1691     /* A packet is selected. */
1692     set_menus_for_selected_packet(cf);
1693 }
1694
1695 static void
1696 main_cf_cb_packet_unselected(capture_file *cf)
1697 {
1698     /* Clear out the display of that packet. */
1699     clear_tree_and_hex_views();
1700
1701     /* No packet is selected. */
1702     set_menus_for_selected_packet(cf);
1703 }
1704
1705 static void
1706 main_cf_cb_field_unselected(capture_file *cf)
1707 {
1708     set_menus_for_selected_tree_row(cf);
1709 }
1710
1711 static void
1712 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1713 {
1714     set_display_filename(&cfile);
1715     set_menus_for_capture_file(&cfile);
1716 }
1717
1718 static void
1719 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1720 {
1721     switch(event) {
1722     case(cf_cb_file_closing):
1723         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1724         main_cf_cb_file_closing(data);
1725         break;
1726     case(cf_cb_file_closed):
1727         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1728         main_cf_cb_file_closed(data);
1729         break;
1730     case(cf_cb_file_read_started):
1731         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1732         main_cf_cb_file_read_started(data);
1733         break;
1734     case(cf_cb_file_read_finished):
1735         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1736         main_cf_cb_file_read_finished(data);
1737         break;
1738     case(cf_cb_packet_selected):
1739         main_cf_cb_packet_selected(data);
1740         break;
1741     case(cf_cb_packet_unselected):
1742         main_cf_cb_packet_unselected(data);
1743         break;
1744     case(cf_cb_field_unselected):
1745         main_cf_cb_field_unselected(data);
1746         break;
1747     case(cf_cb_file_save_started):
1748         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1749         break;
1750     case(cf_cb_file_save_finished):
1751         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1752         break;
1753     case(cf_cb_file_save_reload_finished):
1754         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1755         main_cf_cb_file_save_reload_finished(data);
1756         break;
1757     case(cf_cb_file_save_failed):
1758         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1759         break;
1760     default:
1761         g_warning("main_cf_callback: event %u unknown", event);
1762         g_assert_not_reached();
1763     }
1764 }
1765
1766 #ifdef HAVE_LIBPCAP
1767 static void
1768 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1769 {
1770     switch(event) {
1771     case(capture_cb_capture_prepared):
1772         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1773         main_capture_cb_capture_prepared(capture_opts);
1774         break;
1775     case(capture_cb_capture_update_started):
1776         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1777         main_capture_cb_capture_update_started(capture_opts);
1778         break;
1779     case(capture_cb_capture_update_continue):
1780         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1781         break;
1782     case(capture_cb_capture_update_finished):
1783         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1784         main_capture_cb_capture_update_finished(capture_opts);
1785         break;
1786     case(capture_cb_capture_fixed_started):
1787         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1788         main_capture_cb_capture_fixed_started(capture_opts);
1789         break;
1790     case(capture_cb_capture_fixed_continue):
1791         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1792         break;
1793     case(capture_cb_capture_fixed_finished):
1794         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1795         main_capture_cb_capture_fixed_finished(capture_opts);
1796         break;
1797     case(capture_cb_capture_stopping):
1798         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1799         /* Beware: this state won't be called, if the capture child
1800          * closes the capturing on it's own! */
1801         break;
1802     default:
1803         g_warning("main_capture_callback: event %u unknown", event);
1804         g_assert_not_reached();
1805     }
1806 }
1807 #endif
1808
1809 static void
1810 get_gui_compiled_info(GString *str)
1811 {
1812   get_epan_compiled_version_info(str);
1813
1814   g_string_append(str, ", ");
1815 #ifdef HAVE_LIBPORTAUDIO
1816 #ifdef PORTAUDIO_API_1
1817   g_string_append(str, "with PortAudio <= V18");
1818 #else /* PORTAUDIO_API_1 */
1819   g_string_append(str, "with ");
1820   g_string_append(str, Pa_GetVersionText());
1821 #endif /* PORTAUDIO_API_1 */
1822 #else /* HAVE_LIBPORTAUDIO */
1823   g_string_append(str, "without PortAudio");
1824 #endif /* HAVE_LIBPORTAUDIO */
1825
1826   g_string_append(str, ", ");
1827 #ifdef HAVE_AIRPCAP
1828   get_compiled_airpcap_version(str);
1829 #else
1830   g_string_append(str, "without AirPcap");
1831 #endif
1832 #ifdef NEW_PACKET_LIST
1833   g_string_append(str, ", with new_packet_list");
1834 #endif
1835 }
1836
1837 static void
1838 get_gui_runtime_info(GString *str)
1839 {
1840 #ifdef HAVE_AIRPCAP
1841   g_string_append(str, ", ");
1842   get_runtime_airpcap_version(str);
1843 #endif
1844
1845   if(u3_active()) {
1846     g_string_append(str, ", ");
1847     u3_runtime_info(str);
1848   }
1849
1850 }
1851
1852 static e_prefs *
1853 read_configuration_files(char **gdp_path, char **dp_path)
1854 {
1855   int                  gpf_open_errno, gpf_read_errno;
1856   int                  cf_open_errno, df_open_errno;
1857   int                  gdp_open_errno, gdp_read_errno;
1858   int                  dp_open_errno, dp_read_errno;
1859   char                *gpf_path, *pf_path;
1860   char                *cf_path, *df_path;
1861   int                  pf_open_errno, pf_read_errno;
1862   e_prefs             *prefs_p;
1863
1864   /* Read the preference files. */
1865   prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1866                      &pf_open_errno, &pf_read_errno, &pf_path);
1867
1868   if (gpf_path != NULL) {
1869     if (gpf_open_errno != 0) {
1870       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1871         "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1872         strerror(gpf_open_errno));
1873     }
1874     if (gpf_read_errno != 0) {
1875       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1876         "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1877         strerror(gpf_read_errno));
1878     }
1879   }
1880   if (pf_path != NULL) {
1881     if (pf_open_errno != 0) {
1882       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1883         "Could not open your preferences file\n\"%s\": %s.", pf_path,
1884         strerror(pf_open_errno));
1885     }
1886     if (pf_read_errno != 0) {
1887       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1888         "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1889         strerror(pf_read_errno));
1890     }
1891     g_free(pf_path);
1892     pf_path = NULL;
1893   }
1894
1895 #ifdef _WIN32
1896   /* if the user wants a console to be always there, well, we should open one for him */
1897   if (prefs_p->gui_console_open == console_open_always) {
1898     create_console();
1899   }
1900 #endif
1901
1902   /* Read the capture filter file. */
1903   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1904   if (cf_path != NULL) {
1905       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1906         "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1907         strerror(cf_open_errno));
1908       g_free(cf_path);
1909   }
1910
1911   /* Read the display filter file. */
1912   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1913   if (df_path != NULL) {
1914       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1915         "Could not open your display filter file\n\"%s\": %s.", df_path,
1916         strerror(df_open_errno));
1917       g_free(df_path);
1918   }
1919
1920   /* Read the disabled protocols file. */
1921   read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1922                             dp_path, &dp_open_errno, &dp_read_errno);
1923   if (*gdp_path != NULL) {
1924     if (gdp_open_errno != 0) {
1925       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1926         "Could not open global disabled protocols file\n\"%s\": %s.",
1927         *gdp_path, strerror(gdp_open_errno));
1928     }
1929     if (gdp_read_errno != 0) {
1930       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1931         "I/O error reading global disabled protocols file\n\"%s\": %s.",
1932         *gdp_path, strerror(gdp_read_errno));
1933     }
1934     g_free(*gdp_path);
1935     *gdp_path = NULL;
1936   }
1937   if (*dp_path != NULL) {
1938     if (dp_open_errno != 0) {
1939       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1940         "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1941         strerror(dp_open_errno));
1942     }
1943     if (dp_read_errno != 0) {
1944       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1945         "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1946         strerror(dp_read_errno));
1947     }
1948     g_free(*dp_path);
1949     *dp_path = NULL;
1950   }
1951
1952   return prefs_p;
1953 }
1954
1955 /*  Check if there's something important to tell the user during startup.
1956  *  We want to do this *after* showing the main window so that any windows
1957  *  we pop up will be above the main window.
1958  */
1959 static void
1960 #ifdef _WIN32
1961 check_and_warn_user_startup(gchar *cf_name)
1962 #else
1963 check_and_warn_user_startup(gchar *cf_name _U_)
1964 #endif
1965 {
1966   gchar               *cur_user, *cur_group;
1967   gpointer             priv_warning_dialog;
1968
1969   /* Tell the user not to run as root. */
1970   if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1971     cur_user = get_cur_username();
1972     cur_group = get_cur_groupname();
1973     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1974       "Running as user \"%s\" and group \"%s\".\n"
1975       "This could be dangerous.", cur_user, cur_group);
1976     g_free(cur_user);
1977     g_free(cur_group);
1978     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1979     simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1980   }
1981
1982 #ifdef _WIN32
1983   /* Warn the user if npf.sys isn't loaded. */
1984   if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
1985     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1986       "The NPF driver isn't running.  You may have trouble\n"
1987       "capturing or listing interfaces.");
1988     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1989     simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
1990   }
1991 #endif
1992
1993 }
1994
1995
1996 /* And now our feature presentation... [ fade to music ] */
1997 int
1998 main(int argc, char *argv[])
1999 {
2000   char                *init_progfile_dir_error;
2001   char                *s;
2002   int                  opt;
2003   gboolean             arg_error = FALSE;
2004
2005   extern int           info_update_freq;  /* Found in about_dlg.c. */
2006   const gchar         *filter;
2007
2008 #ifdef _WIN32
2009   WSADATA              wsaData;
2010 #endif  /* _WIN32 */
2011
2012   char                *rf_path;
2013   int                  rf_open_errno;
2014   char                *gdp_path, *dp_path;
2015   int                  err;
2016 #ifdef HAVE_LIBPCAP
2017   gboolean             start_capture = FALSE;
2018   gboolean             list_link_layer_types = FALSE;
2019   GList               *if_list;
2020   gchar               *err_str;
2021 #else
2022   gboolean             capture_option_specified = FALSE;
2023 #ifdef _WIN32
2024 #ifdef HAVE_AIRPCAP
2025   gchar               *err_str;
2026 #endif
2027 #endif
2028 #endif
2029   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2030   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2031   dfilter_t           *rfcode = NULL;
2032   gboolean             rfilter_parse_failed = FALSE;
2033   e_prefs             *prefs_p;
2034   char                 badopt;
2035   GtkWidget           *splash_win = NULL;
2036   GLogLevelFlags       log_flags;
2037   guint                go_to_packet = 0;
2038   gboolean             jump_backwards = FALSE, saved_bw = FALSE;
2039   dfilter_t           *jump_to_filter = NULL;
2040   int                  optind_initial;
2041   int                  status;
2042
2043 #ifdef HAVE_LIBPCAP
2044 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2045 #define OPTSTRING_B "B:"
2046 #else
2047 #define OPTSTRING_B ""
2048 #endif  /* _WIN32 or HAVE_PCAP_CREATE */
2049 #else /* HAVE_LIBPCAP */
2050 #define OPTSTRING_B ""
2051 #endif  /* HAVE_LIBPCAP */
2052
2053 #ifdef HAVE_PCAP_CREATE
2054 #define OPTSTRING_I "I"
2055 #else
2056 #define OPTSTRING_I ""
2057 #endif
2058
2059 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:u:vw:X:y:z:"
2060
2061   static const char optstring[] = OPTSTRING;
2062
2063   /*
2064    * Get credential information for later use, and drop privileges
2065    * before doing anything else.
2066    * Let the user know if anything happened.
2067    */
2068   get_credential_info();
2069   relinquish_special_privs_perm();
2070
2071   /*
2072    * Attempt to get the pathname of the executable file.
2073    */
2074   init_progfile_dir_error = init_progfile_dir(argv[0], main);
2075
2076   /* initialize the funnel mini-api */
2077   initialize_funnel_ops();
2078
2079 #ifdef  HAVE_AIRPDCAP
2080   AirPDcapInitContext(&airpdcap_ctx);
2081 #endif
2082
2083 #ifdef _WIN32
2084   /* Load wpcap if possible. Do this before collecting the run-time version information */
2085   load_wpcap();
2086
2087   /* ... and also load the packet.dll from wpcap */
2088   wpcap_packet_load();
2089
2090 #ifdef HAVE_AIRPCAP
2091   /* Load the airpcap.dll.  This must also be done before collecting
2092    * run-time version information. */
2093   airpcap_dll_ret_val = load_airpcap();
2094
2095   switch (airpcap_dll_ret_val) {
2096   case AIRPCAP_DLL_OK:
2097     /* load the airpcap interfaces */
2098     airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2099
2100     if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2101       if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2102         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2103         g_free(err_str);
2104       }
2105       airpcap_if_active = NULL;
2106
2107     } else {
2108
2109       /* select the first ad default (THIS SHOULD BE CHANGED) */
2110       airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2111           }
2112     break;
2113 #if 0
2114     /*
2115      * XXX - Maybe we need to warn the user if one of the following happens???
2116      */
2117     case AIRPCAP_DLL_OLD:
2118       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2119       break;
2120
2121     case AIRPCAP_DLL_ERROR:
2122       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2123       break;
2124
2125     case AIRPCAP_DLL_NOT_FOUND:
2126       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2127       break;
2128 #endif
2129   }
2130 #endif /* HAVE_AIRPCAP */
2131
2132   /* Start windows sockets */
2133   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2134 #endif  /* _WIN32 */
2135
2136   profile_store_persconffiles (TRUE);
2137
2138   /* Assemble the compile-time version information string */
2139   comp_info_str = g_string_new("Compiled ");
2140
2141   g_string_append(comp_info_str, "with ");
2142   g_string_append_printf(comp_info_str,
2143 #ifdef GTK_MAJOR_VERSION
2144                     "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2145                     GTK_MICRO_VERSION);
2146 #else
2147                     "GTK+ (version unknown)");
2148 #endif
2149   g_string_append(comp_info_str, ", ");
2150
2151   get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2152
2153   /* Assemble the run-time version information string */
2154   runtime_info_str = g_string_new("Running ");
2155   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2156
2157   /* Read the profile independent recent file.  We have to do this here so we can */
2158   /* set the profile before it can be set from the command line parameterts */
2159   recent_read_static(&rf_path, &rf_open_errno);
2160   if (rf_path != NULL && rf_open_errno != 0) {
2161     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2162                   "Could not open common recent file\n\"%s\": %s.",
2163                   rf_path, strerror(rf_open_errno));
2164   }
2165
2166   /* "pre-scan" the command line parameters, if we have "console only"
2167      parameters.  We do this so we don't start GTK+ if we're only showing
2168      command-line help or version information.
2169
2170      XXX - this pre-scan is done before we start GTK+, so we haven't
2171      run gtk_init() on the arguments.  That means that GTK+ arguments
2172      have not been removed from the argument list; those arguments
2173      begin with "--", and will be treated as an error by getopt().
2174
2175      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2176      error messages. */
2177   opterr = 0;
2178   optind_initial = optind;
2179   while ((opt = getopt(argc, argv, optstring)) != -1) {
2180     switch (opt) {
2181       case 'C':        /* Configuration Profile */
2182         if (profile_exists (optarg)) {
2183           set_profile_name (optarg);
2184         } else {
2185           cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2186           exit(1);
2187         }
2188         break;
2189       case 'h':        /* Print help and exit */
2190         print_usage(TRUE);
2191         exit(0);
2192         break;
2193 #ifdef _WIN32
2194       case 'i':
2195         if (strcmp(optarg, "-") == 0)
2196           stdin_capture = TRUE;
2197         break;
2198 #endif
2199       case 'P':        /* Path settings - change these before the Preferences and alike are processed */
2200         status = filesystem_opt(opt, optarg);
2201         if(status != 0) {
2202             cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2203             exit(status);
2204         }
2205         break;
2206       case 'v':        /* Show version and exit */
2207         show_version();
2208         exit(0);
2209         break;
2210       case 'X':
2211         /*
2212          *  Extension command line options have to be processed before
2213          *  we call epan_init() as they are supposed to be used by dissectors
2214          *  or taps very early in the registration process.
2215          */
2216         ex_opt_add(optarg);
2217         break;
2218       case '?':        /* Ignore errors - the "real" scan will catch them. */
2219         break;
2220     }
2221   }
2222
2223   /* Init the "Open file" dialog directory */
2224   /* (do this after the path settings are processed) */
2225   set_last_open_dir(get_persdatafile_dir());
2226
2227   /* Set getopt index back to initial value, so it will start with the
2228      first command line parameter again.  Also reset opterr to 1, so that
2229      error messages are printed by getopt().
2230
2231      XXX - this seems to work on most platforms, but time will tell.
2232      The Single UNIX Specification says "The getopt() function need
2233      not be reentrant", so this isn't guaranteed to work.  The Mac
2234      OS X 10.4[.x] getopt() man page says
2235
2236        In order to use getopt() to evaluate multiple sets of arguments, or to
2237        evaluate a single set of arguments multiple times, the variable optreset
2238        must be set to 1 before the second and each additional set of calls to
2239        getopt(), and the variable optind must be reinitialized.
2240
2241            ...
2242
2243        The optreset variable was added to make it possible to call the getopt()
2244        function multiple times.  This is an extension to the IEEE Std 1003.2
2245        (``POSIX.2'') specification.
2246
2247      which I think comes from one of the other BSDs.
2248
2249      XXX - if we want to control all the command-line option errors, so
2250      that we can display them where we choose (e.g., in a window), we'd
2251      want to leave opterr as 0, and produce our own messages using optopt.
2252      We'd have to check the value of optopt to see if it's a valid option
2253      letter, in which case *presumably* the error is "this option requires
2254      an argument but none was specified", or not a valid option letter,
2255      in which case *presumably* the error is "this option isn't valid".
2256      Some versions of getopt() let you supply a option string beginning
2257      with ':', which means that getopt() will return ':' rather than '?'
2258      for "this option requires an argument but none was specified", but
2259      not all do. */
2260   optind = optind_initial;
2261   opterr = 1;
2262
2263   /* Set the current locale according to the program environment.
2264    * We haven't localized anything, but some GTK widgets are localized
2265    * (the file selection dialogue, for example).
2266    * This also sets the C-language locale to the native environment. */
2267   gtk_set_locale();
2268
2269   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2270   gtk_init (&argc, &argv);
2271
2272   cf_callback_add(main_cf_callback, NULL);
2273 #ifdef HAVE_LIBPCAP
2274   capture_callback_add(main_capture_callback, NULL);
2275 #endif
2276   cf_callback_add(statusbar_cf_callback, NULL);
2277 #ifdef HAVE_LIBPCAP
2278   capture_callback_add(statusbar_capture_callback, NULL);
2279 #endif
2280
2281   /* Arrange that if we have no console window, and a GLib message logging
2282      routine is called to log a message, we pop up a console window.
2283
2284      We do that by inserting our own handler for all messages logged
2285      to the default domain; that handler pops up a console if necessary,
2286      and then calls the default handler. */
2287
2288   /* We might want to have component specific log levels later ... */
2289
2290   log_flags =
2291                     G_LOG_LEVEL_ERROR|
2292                     G_LOG_LEVEL_CRITICAL|
2293                     G_LOG_LEVEL_WARNING|
2294                     G_LOG_LEVEL_MESSAGE|
2295                     G_LOG_LEVEL_INFO|
2296                     G_LOG_LEVEL_DEBUG|
2297                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2298
2299   g_log_set_handler(NULL,
2300                     log_flags,
2301                     console_log_handler, NULL /* user_data */);
2302   g_log_set_handler(LOG_DOMAIN_MAIN,
2303                     log_flags,
2304                     console_log_handler, NULL /* user_data */);
2305
2306 #ifdef HAVE_LIBPCAP
2307   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2308                     log_flags,
2309                     console_log_handler, NULL /* user_data */);
2310   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2311                     log_flags,
2312                     console_log_handler, NULL /* user_data */);
2313
2314   /* Set the initial values in the capture options. This might be overwritten
2315      by preference settings and then again by the command line parameters. */
2316   capture_opts_init(&global_capture_opts, &cfile);
2317
2318   global_capture_opts.snaplen             = MIN_PACKET_SIZE;
2319   global_capture_opts.has_ring_num_files  = TRUE;
2320 #endif
2321
2322   /* Initialize whatever we need to allocate colors for GTK+ */
2323   colors_init();
2324
2325   /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2326   filter = get_conn_cfilter();
2327   if ( *filter != '\0' ) {
2328     info_update_freq = 1000;  /* Milliseconds */
2329   }
2330
2331   /* We won't come till here, if we had a "console only" command line parameter. */
2332   splash_win = splash_new("Loading Wireshark ...");
2333   if (init_progfile_dir_error != NULL) {
2334     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2335         "Can't get pathname of Wireshark: %s.\n"
2336         "It won't be possible to capture traffic.\n"
2337         "Report this to the Wireshark developers.",
2338         init_progfile_dir_error);
2339     g_free(init_progfile_dir_error);
2340   }
2341
2342   splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2343
2344   /* Register all dissectors; we must do this before checking for the
2345      "-G" flag, as the "-G" flag dumps information registered by the
2346      dissectors, and we must do it before we read the preferences, in
2347      case any dissectors register preferences. */
2348   epan_init(register_all_protocols,register_all_protocol_handoffs,
2349             splash_update, (gpointer) splash_win,
2350             failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2351             write_failure_alert_box);
2352
2353   splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2354
2355   /* Register all tap listeners; we do this before we parse the arguments,
2356      as the "-z" argument can specify a registered tap. */
2357
2358   /* we register the plugin taps before the other taps because
2359           stats_tree taps plugins will be registered as tap listeners
2360           by stats_tree_stat.c and need to registered before that */
2361
2362 #ifdef HAVE_PLUGINS
2363   register_all_plugin_tap_listeners();
2364 #endif
2365
2366   register_all_tap_listeners();
2367
2368   splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2369
2370   /* Now register the preferences for any non-dissector modules.
2371      We must do that before we read the preferences as well. */
2372   prefs_register_modules();
2373
2374   prefs_p = read_configuration_files (&gdp_path, &dp_path);
2375
2376   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2377 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2378   {
2379       GThread *ut;
2380       g_thread_init(NULL);
2381       gdk_threads_init();
2382       ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2383       g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2384   }
2385 #else  /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2386   /* this is to keep tap extensions updating once every 3 seconds */
2387   tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2388 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2389
2390   splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2391
2392
2393   /* Read the profile dependent (static part) of the recent file. */
2394   /* Only the static part of it will be read, as we don't have the gui now to fill the */
2395   /* recent lists which is done in the dynamic part. */
2396   /* We have to do this already here, so command line parameters can overwrite these values. */
2397   recent_read_profile_static(&rf_path, &rf_open_errno);
2398   if (rf_path != NULL && rf_open_errno != 0) {
2399     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2400                   "Could not open recent file\n\"%s\": %s.",
2401                   rf_path, strerror(rf_open_errno));
2402   }
2403
2404   cap_file_init(&cfile);
2405
2406   /* Fill in capture options with values from the preferences */
2407   prefs_to_capture_opts();
2408
2409   /* Now get our args */
2410   while ((opt = getopt(argc, argv, optstring)) != -1) {
2411     switch (opt) {
2412       /*** capture option specific ***/
2413       case 'a':        /* autostop criteria */
2414       case 'b':        /* Ringbuffer option */
2415       case 'c':        /* Capture xxx packets */
2416       case 'f':        /* capture filter */
2417       case 'k':        /* Start capture immediately */
2418       case 'H':        /* Hide capture info dialog box */
2419       case 'i':        /* Use interface xxx */
2420       case 'p':        /* Don't capture in promiscuous mode */
2421 #ifdef HAVE_PCAP_CREATE
2422       case 'I':        /* Capture in monitor mode, if available */
2423 #endif
2424       case 'Q':        /* Quit after capture (just capture to file) */
2425       case 's':        /* Set the snapshot (capture) length */
2426       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2427       case 'w':        /* Write to capture file xxx */
2428       case 'y':        /* Set the pcap data link type */
2429 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2430       case 'B':        /* Buffer size */
2431 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2432 #ifdef HAVE_LIBPCAP
2433         status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2434                                       &start_capture);
2435         if(status != 0) {
2436             exit(status);
2437         }
2438 #else
2439         capture_option_specified = TRUE;
2440         arg_error = TRUE;
2441 #endif
2442         break;
2443
2444 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2445       case 'K':        /* Kerberos keytab file */
2446         read_keytab_file(optarg);
2447         break;
2448 #endif
2449
2450       /*** all non capture option specific ***/
2451       case 'C':
2452         /* Configuration profile settings were already processed just ignore them this time*/
2453         break;
2454       case 'D':        /* Print a list of capture devices and exit */
2455 #ifdef HAVE_LIBPCAP
2456         if_list = capture_interface_list(&err, &err_str);
2457         if (if_list == NULL) {
2458           switch (err) {
2459           case CANT_GET_INTERFACE_LIST:
2460             cmdarg_err("%s", err_str);
2461             g_free(err_str);
2462             break;
2463
2464           case NO_INTERFACES_FOUND:
2465             cmdarg_err("There are no interfaces on which a capture can be done");
2466             break;
2467           }
2468           exit(2);
2469         }
2470         capture_opts_print_interfaces(if_list);
2471         free_interface_list(if_list);
2472         exit(0);
2473 #else
2474         capture_option_specified = TRUE;
2475         arg_error = TRUE;
2476 #endif
2477         break;
2478       case 'j':        /* Search backwards for a matching packet from filter in option J */
2479         jump_backwards = TRUE;
2480         break;
2481       case 'g':        /* Go to packet with the given packet number */
2482         go_to_packet = get_positive_int(optarg, "go to packet");
2483         break;
2484       case 'J':        /* Jump to the first packet which matches the filter criteria */
2485         jfilter = optarg;
2486         break;
2487       case 'l':        /* Automatic scrolling in live capture mode */
2488 #ifdef HAVE_LIBPCAP
2489         auto_scroll_live = TRUE;
2490 #else
2491         capture_option_specified = TRUE;
2492         arg_error = TRUE;
2493 #endif
2494         break;
2495       case 'L':        /* Print list of link-layer types and exit */
2496 #ifdef HAVE_LIBPCAP
2497         list_link_layer_types = TRUE;
2498 #else
2499         capture_option_specified = TRUE;
2500         arg_error = TRUE;
2501 #endif
2502         break;
2503       case 'm':        /* Fixed-width font for the display */
2504         g_free(prefs_p->gui_font_name);
2505         prefs_p->gui_font_name = g_strdup(optarg);
2506         break;
2507       case 'n':        /* No name resolution */
2508         g_resolv_flags = RESOLV_NONE;
2509         break;
2510       case 'N':        /* Select what types of addresses/port #s to resolve */
2511         if (g_resolv_flags == RESOLV_ALL)
2512           g_resolv_flags = RESOLV_NONE;
2513         badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2514         if (badopt != '\0') {
2515           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2516                         badopt);
2517           exit(1);
2518         }
2519         break;
2520       case 'o':        /* Override preference from command line */
2521         switch (prefs_set_pref(optarg)) {
2522         case PREFS_SET_OK:
2523           break;
2524         case PREFS_SET_SYNTAX_ERR:
2525           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2526           exit(1);
2527           break;
2528         case PREFS_SET_NO_SUCH_PREF:
2529           /* not a preference, might be a recent setting */
2530           switch (recent_set_arg(optarg)) {
2531             case PREFS_SET_OK:
2532               break;
2533             case PREFS_SET_SYNTAX_ERR:
2534               /* shouldn't happen, checked already above */
2535               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2536               exit(1);
2537               break;
2538             case PREFS_SET_NO_SUCH_PREF:
2539             case PREFS_SET_OBSOLETE:
2540               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2541                     optarg);
2542               exit(1);
2543               break;
2544             default:
2545               g_assert_not_reached();
2546             }
2547           break;
2548         case PREFS_SET_OBSOLETE:
2549           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2550                         optarg);
2551           exit(1);
2552           break;
2553         default:
2554           g_assert_not_reached();
2555         }
2556         break;
2557       case 'P':
2558         /* Path settings were already processed just ignore them this time*/
2559         break;
2560       case 'r':        /* Read capture file xxx */
2561         /* We may set "last_open_dir" to "cf_name", and if we change
2562            "last_open_dir" later, we free the old value, so we have to
2563            set "cf_name" to something that's been allocated. */
2564 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2565         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2566         cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2567 #else
2568         cf_name = g_strdup(optarg);
2569 #endif
2570         break;
2571       case 'R':        /* Read file filter */
2572         rfilter = optarg;
2573         break;
2574       case 't':        /* Time stamp type */
2575         if (strcmp(optarg, "r") == 0)
2576           timestamp_set_type(TS_RELATIVE);
2577         else if (strcmp(optarg, "a") == 0)
2578           timestamp_set_type(TS_ABSOLUTE);
2579         else if (strcmp(optarg, "ad") == 0)
2580           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2581         else if (strcmp(optarg, "d") == 0)
2582           timestamp_set_type(TS_DELTA);
2583         else if (strcmp(optarg, "dd") == 0)
2584           timestamp_set_type(TS_DELTA_DIS);
2585         else if (strcmp(optarg, "e") == 0)
2586           timestamp_set_type(TS_EPOCH);
2587         else {
2588           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2589           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2590           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2591           exit(1);
2592         }
2593         break;
2594       case 'u':        /* Seconds type */
2595         if (strcmp(optarg, "s") == 0)
2596           timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2597         else if (strcmp(optarg, "hms") == 0)
2598           timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2599         else {
2600           cmdarg_err("Invalid seconds type \"%s\"", optarg);
2601           cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2602           exit(1);
2603         }
2604         break;
2605       case 'X':
2606           /* ext ops were already processed just ignore them this time*/
2607           break;
2608       case 'z':
2609         /* We won't call the init function for the stat this soon
2610            as it would disallow MATE's fields (which are registered
2611            by the preferences set callback) from being used as
2612            part of a tap filter.  Instead, we just add the argument
2613            to a list of stat arguments. */
2614         if (!process_stat_cmd_arg(optarg)) {
2615           cmdarg_err("Invalid -z argument.");
2616           cmdarg_err_cont("  -z argument must be one of :");
2617           list_stat_cmd_args();
2618           exit(1);
2619         }
2620         break;
2621       default:
2622       case '?':        /* Bad flag - print usage message */
2623         arg_error = TRUE;
2624         break;
2625     }
2626   }
2627   argc -= optind;
2628   argv += optind;
2629   if (argc >= 1) {
2630     if (cf_name != NULL) {
2631       /*
2632        * Input file name specified with "-r" *and* specified as a regular
2633        * command-line argument.
2634        */
2635       cmdarg_err("File name specified both with -r and regular argument");
2636       arg_error = TRUE;
2637     } else {
2638       /*
2639        * Input file name not specified with "-r", and a command-line argument
2640        * was specified; treat it as the input file name.
2641        *
2642        * Yes, this is different from tshark, where non-flag command-line
2643        * arguments are a filter, but this works better on GUI desktops
2644        * where a command can be specified to be run to open a particular
2645        * file - yes, you could have "-r" as the last part of the command,
2646        * but that's a bit ugly.
2647        */
2648 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2649       /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2650       cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2651 #else
2652       cf_name = g_strdup(argv[0]);
2653 #endif
2654     }
2655     argc--;
2656     argv++;
2657   }
2658
2659
2660
2661   if (argc != 0) {
2662     /*
2663      * Extra command line arguments were specified; complain.
2664      */
2665     cmdarg_err("Invalid argument: %s", argv[0]);
2666     arg_error = TRUE;
2667   }
2668
2669   if (arg_error) {
2670 #ifndef HAVE_LIBPCAP
2671     if (capture_option_specified) {
2672       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2673     }
2674 #endif
2675     print_usage(FALSE);
2676     exit(1);
2677   }
2678
2679 #ifdef HAVE_LIBPCAP
2680   if (start_capture && list_link_layer_types) {
2681     /* Specifying *both* is bogus. */
2682     cmdarg_err("You can't specify both -L and a live capture.");
2683     exit(1);
2684   }
2685
2686   if (list_link_layer_types) {
2687     /* We're supposed to list the link-layer types for an interface;
2688        did the user also specify a capture file to be read? */
2689     if (cf_name) {
2690       /* Yes - that's bogus. */
2691       cmdarg_err("You can't specify -L and a capture file to be read.");
2692       exit(1);
2693     }
2694     /* No - did they specify a ring buffer option? */
2695     if (global_capture_opts.multi_files_on) {
2696       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2697       exit(1);
2698     }
2699   } else {
2700     /* We're supposed to do a live capture; did the user also specify
2701        a capture file to be read? */
2702     if (start_capture && cf_name) {
2703       /* Yes - that's bogus. */
2704       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2705       exit(1);
2706     }
2707
2708     /* No - was the ring buffer option specified and, if so, does it make
2709        sense? */
2710     if (global_capture_opts.multi_files_on) {
2711       /* Ring buffer works only under certain conditions:
2712          a) ring buffer does not work with temporary files;
2713          b) real_time_mode and multi_files_on are mutually exclusive -
2714             real_time_mode takes precedence;
2715          c) it makes no sense to enable the ring buffer if the maximum
2716             file size is set to "infinite". */
2717       if (global_capture_opts.save_file == NULL) {
2718         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2719         global_capture_opts.multi_files_on = FALSE;
2720       }
2721 /*      if (global_capture_opts.real_time_mode) {
2722         cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2723         global_capture_opts.multi_files_on = FALSE;
2724       }*/
2725       if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2726         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2727 /* XXX - this must be redesigned as the conditions changed */
2728 /*      global_capture_opts.multi_files_on = FALSE;*/
2729       }
2730     }
2731   }
2732
2733   if (start_capture || list_link_layer_types) {
2734     /* Did the user specify an interface to use? */
2735     if (!capture_opts_trim_iface(&global_capture_opts,
2736         (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2737         exit(2);
2738     }
2739   }
2740
2741   if (list_link_layer_types) {
2742     /* Get the list of link-layer types for the capture device. */
2743     if_capabilities_t *caps;
2744
2745     caps = capture_get_if_capabilities(global_capture_opts.iface,
2746                                        global_capture_opts.monitor_mode,
2747                                        &err_str);
2748     if (caps == NULL) {
2749       cmdarg_err("%s", err_str);
2750       g_free(err_str);
2751       exit(2);
2752     }
2753     if (caps->data_link_types == NULL) {
2754       cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2755       exit(2);
2756     }
2757     capture_opts_print_if_capabilities(caps, global_capture_opts.monitor_mode);
2758     free_if_capabilities(caps);
2759     exit(0);
2760   }
2761
2762   capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2763   capture_opts_trim_ring_num_files(&global_capture_opts);
2764 #endif /* HAVE_LIBPCAP */
2765
2766   /* Notify all registered modules that have had any of their preferences
2767      changed either from one of the preferences file or from the command
2768      line that their preferences have changed. */
2769   prefs_apply_all();
2770
2771   /* disabled protocols as per configuration file */
2772   if (gdp_path == NULL && dp_path == NULL) {
2773     set_disabled_protos_list();
2774   }
2775
2776   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2777
2778   /* read in rc file from global and personal configuration paths. */
2779   rc_file = get_datafile_path(RC_FILE);
2780   gtk_rc_parse(rc_file);
2781   g_free(rc_file);
2782   rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2783   gtk_rc_parse(rc_file);
2784   g_free(rc_file);
2785
2786   font_init();
2787
2788   stock_icons_init();
2789
2790   /* close the splash screen, as we are going to open the main window now */
2791   splash_destroy(splash_win);
2792
2793   /************************************************************************/
2794   /* Everything is prepared now, preferences and command line was read in */
2795
2796   /* Pop up the main window. */
2797   create_main_window(pl_size, tv_size, bv_size, prefs_p);
2798
2799   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2800   recent_read_dynamic(&rf_path, &rf_open_errno);
2801   if (rf_path != NULL && rf_open_errno != 0) {
2802     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2803                   "Could not open recent file\n\"%s\": %s.",
2804                   rf_path, strerror(rf_open_errno));
2805   }
2806
2807   color_filters_enable(recent.packet_list_colorize);
2808
2809   /* rearrange all the widgets as we now have all recent settings ready for this */
2810   main_widgets_rearrange();
2811
2812   /* Fill in column titles.  This must be done after the top level window
2813      is displayed.
2814
2815      XXX - is that still true, with fixed-width columns? */
2816 #ifndef NEW_PACKET_LIST
2817   packet_list_set_column_titles();
2818 #endif
2819
2820   menu_recent_read_finished();
2821 #ifdef HAVE_LIBPCAP
2822   menu_auto_scroll_live_changed(auto_scroll_live);
2823 #endif
2824
2825   switch (user_font_apply()) {
2826   case FA_SUCCESS:
2827       break;
2828   case FA_FONT_NOT_RESIZEABLE:
2829       /* "user_font_apply()" popped up an alert box. */
2830       /* turn off zooming - font can't be resized */
2831   case FA_FONT_NOT_AVAILABLE:
2832       /* XXX - did we successfully load the un-zoomed version earlier?
2833       If so, this *probably* means the font is available, but not at
2834       this particular zoom level, but perhaps some other failure
2835       occurred; I'm not sure you can determine which is the case,
2836       however. */
2837       /* turn off zooming - zoom level is unavailable */
2838   default:
2839       /* in any other case than FA_SUCCESS, turn off zooming */
2840       recent.gui_zoom_level = 0;
2841       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2842   }
2843
2844   dnd_init(top_level);
2845
2846   color_filters_init();
2847   decode_as_init();
2848
2849   /* the window can be sized only, if it's not already shown, so do it now! */
2850   main_load_window_geometry(top_level);
2851
2852   g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2853
2854
2855   /* If we were given the name of a capture file, read it in now;
2856      we defer it until now, so that, if we can't open it, and pop
2857      up an alert box, the alert box is more likely to come up on
2858      top of the main window - but before the preference-file-error
2859      alert box, so, if we get one of those, it's more likely to come
2860      up on top of us. */
2861   if (cf_name) {
2862     show_main_window(TRUE);
2863     check_and_warn_user_startup(cf_name);
2864     if (rfilter != NULL) {
2865       if (!dfilter_compile(rfilter, &rfcode)) {
2866         bad_dfilter_alert_box(rfilter);
2867         rfilter_parse_failed = TRUE;
2868       }
2869     }
2870     if (!rfilter_parse_failed) {
2871       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2872         /* "cf_open()" succeeded, so it closed the previous
2873            capture file, and thus destroyed any previous read filter
2874            attached to "cf". */
2875
2876         cfile.rfcode = rfcode;
2877         /* Open stat windows; we do so after creating the main window,
2878            to avoid GTK warnings, and after successfully opening the
2879            capture file, so we know we have something to compute stats
2880            on, and after registering all dissectors, so that MATE will
2881            have registered its field array and we can have a tap filter
2882            with one of MATE's late-registered fields as part of the
2883            filter. */
2884         start_requested_stats();
2885
2886         /* Read the capture file. */
2887         switch (cf_read(&cfile, FALSE)) {
2888
2889         case CF_READ_OK:
2890         case CF_READ_ERROR:
2891           /* Just because we got an error, that doesn't mean we were unable
2892              to read any of the file; we handle what we could get from the
2893              file. */
2894           /* if the user told us to jump to a specific packet, do it now */
2895           if(go_to_packet != 0) {
2896             /* Jump to the specified frame number, kept for backward
2897                compatibility. */
2898             cf_goto_frame(&cfile, go_to_packet);
2899           } else if (jfilter != NULL) {
2900             /* try to compile given filter */
2901             if (!dfilter_compile(jfilter, &jump_to_filter)) {
2902               bad_dfilter_alert_box(jfilter);
2903             } else
2904             {
2905               /* Filter ok, jump to the first packet matching the filter
2906                  conditions. Default search direction is forward, but if
2907                  option d was given, search backwards */
2908               saved_bw = cfile.sbackward;
2909               cfile.sbackward = jump_backwards;
2910               cf_find_packet_dfilter(&cfile, jump_to_filter);
2911               cfile.sbackward = saved_bw;
2912             }
2913           }
2914           break;
2915
2916         case CF_READ_ABORTED:
2917           /* Exit now. */
2918           exit(0);
2919           break;
2920         }
2921         /* Save the name of the containing directory specified in the
2922            path name, if any; we can write over cf_name, which is a
2923            good thing, given that "get_dirname()" does write over its
2924            argument. */
2925         s = get_dirname(cf_name);
2926         set_last_open_dir(s);
2927         g_free(cf_name);
2928         cf_name = NULL;
2929       } else {
2930         if (rfcode != NULL)
2931           dfilter_free(rfcode);
2932         cfile.rfcode = NULL;
2933         show_main_window(FALSE);
2934         /* Don't call check_and_warn_user_startup(): we did it above */
2935         set_menus_for_capture_in_progress(FALSE);
2936         set_capture_if_dialog_for_capture_in_progress(FALSE);
2937       }
2938     }
2939   } else {
2940 #ifdef HAVE_LIBPCAP
2941     if (start_capture) {
2942       if (global_capture_opts.save_file != NULL) {
2943         /* Save the directory name for future file dialogs. */
2944         /* (get_dirname overwrites filename) */
2945         s = get_dirname(g_strdup(global_capture_opts.save_file));
2946         set_last_open_dir(s);
2947         g_free(s);
2948       }
2949       /* "-k" was specified; start a capture. */
2950       show_main_window(TRUE);
2951       check_and_warn_user_startup(cf_name);
2952       if (capture_start(&global_capture_opts)) {
2953         /* The capture started.  Open stat windows; we do so after creating
2954            the main window, to avoid GTK warnings, and after successfully
2955            opening the capture file, so we know we have something to compute
2956            stats on, and after registering all dissectors, so that MATE will
2957            have registered its field array and we can have a tap filter with
2958            one of MATE's late-registered fields as part of the filter. */
2959         start_requested_stats();
2960       }
2961     }
2962     else {
2963       show_main_window(FALSE);
2964       check_and_warn_user_startup(cf_name);
2965       set_menus_for_capture_in_progress(FALSE);
2966       set_capture_if_dialog_for_capture_in_progress(FALSE);
2967     }
2968
2969     /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2970     if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2971       g_free(global_capture_opts.cfilter);
2972       global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2973     }
2974 #else /* HAVE_LIBPCAP */
2975     show_main_window(FALSE);
2976     check_and_warn_user_startup(cf_name);
2977     set_menus_for_capture_in_progress(FALSE);
2978     set_capture_if_dialog_for_capture_in_progress(FALSE);
2979 #endif /* HAVE_LIBPCAP */
2980   }
2981
2982   /* register our pid if we are being run from a U3 device */
2983   u3_register_pid();
2984
2985   profile_store_persconffiles (FALSE);
2986
2987   g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2988
2989   /* we'll enter the GTK loop now and hand the control over to GTK ... */
2990   gtk_main();
2991   /* ... back from GTK, we're going down now! */
2992
2993   /* deregister our pid */
2994   u3_deregister_pid();
2995
2996   epan_cleanup();
2997
2998 #ifdef  HAVE_AIRPDCAP
2999         AirPDcapDestroyContext(&airpdcap_ctx);
3000 #endif
3001
3002 #ifdef _WIN32
3003   /* hide the (unresponsive) main window, while asking the user to close the console window */
3004   gtk_widget_hide(top_level);
3005
3006   /* Shutdown windows sockets */
3007   WSACleanup();
3008
3009   /* For some unknown reason, the "atexit()" call in "create_console()"
3010      doesn't arrange that "destroy_console()" be called when we exit,
3011      so we call it here if a console was created. */
3012   destroy_console();
3013 #endif
3014
3015   exit(0);
3016 }
3017
3018 #ifdef _WIN32
3019
3020 /* We build this as a GUI subsystem application on Win32, so
3021    "WinMain()", not "main()", gets called.
3022
3023    Hack shamelessly stolen from the Win32 port of the GIMP. */
3024 #ifdef __GNUC__
3025 #define _stdcall  __attribute__((stdcall))
3026 #endif
3027
3028 int _stdcall
3029 WinMain (struct HINSTANCE__ *hInstance,
3030          struct HINSTANCE__ *hPrevInstance,
3031          char               *lpszCmdLine,
3032          int                 nCmdShow)
3033 {
3034   INITCOMMONCONTROLSEX comm_ctrl;
3035
3036   /* Initialize our controls. Required for native Windows file dialogs. */
3037   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3038   comm_ctrl.dwSize = sizeof(comm_ctrl);
3039   /* Includes the animate, header, hot key, list view, progress bar,
3040    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3041    * up-down controls
3042    */
3043   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3044   InitCommonControlsEx(&comm_ctrl);
3045
3046   /* RichEd20.DLL is needed for filter entries. */
3047   LoadLibrary(_T("riched20.dll"));
3048
3049   has_console = FALSE;
3050   return main (__argc, __argv);
3051 }
3052
3053 /* The code to create and desstroy console windows should not be necessary,
3054    at least as I read the GLib source code, as it looks as if GLib is, on
3055    Win32, *supposed* to create a console window into which to display its
3056    output.
3057
3058    That doesn't happen, however.  I suspect there's something completely
3059    broken about that code in GLib-for-Win32, and that it may be related
3060    to the breakage that forces us to just call "printf()" on the message
3061    rather than passing the message on to "g_log_default_handler()"
3062    (which is the routine that does the aforementioned non-functional
3063    console window creation).  */
3064
3065 /*
3066  * If this application has no console window to which its standard output
3067  * would go, create one.
3068  */
3069 void
3070 create_console(void)
3071 {
3072   if (stdin_capture) {
3073     /* We've been handed "-i -". Don't mess with stdio. */
3074     return;
3075   }
3076
3077   if (!has_console) {
3078     /* We have no console to which to print the version string, so
3079        create one and make it the standard input, output, and error. */
3080     if (!AllocConsole())
3081       return;   /* couldn't create console */
3082
3083     ws_freopen("CONIN$", "r", stdin);
3084     ws_freopen("CONOUT$", "w", stdout);
3085     ws_freopen("CONOUT$", "w", stderr);
3086
3087     /* Well, we have a console now. */
3088     has_console = TRUE;
3089
3090     /* Now register "destroy_console()" as a routine to be called just
3091        before the application exits, so that we can destroy the console
3092        after the user has typed a key (so that the console doesn't just
3093        disappear out from under them, giving the user no chance to see
3094        the message(s) we put in there). */
3095     atexit(destroy_console);
3096
3097     SetConsoleTitle(_T("Wireshark Debug Console"));
3098   }
3099 }
3100
3101 static void
3102 destroy_console(void)
3103 {
3104   if (has_console) {
3105     printf("\n\nPress any key to exit\n");
3106     _getch();
3107     FreeConsole();
3108   }
3109 }
3110 #endif /* _WIN32 */
3111
3112
3113 static void
3114 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3115                     const char *message, gpointer user_data _U_)
3116 {
3117   time_t curr;
3118   struct tm *today;
3119   const char *level;
3120
3121
3122   /* ignore log message, if log_level isn't interesting based
3123      upon the console log preferences.
3124      If the preferences haven't been loaded loaded yet, display the
3125      message anyway.
3126
3127      The default console_log_level preference value is such that only
3128        ERROR, CRITICAL and WARNING level messages are processed;
3129        MESSAGE, INFO and DEBUG level messages are ignored.  */
3130   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3131      prefs.console_log_level != 0) {
3132     return;
3133   }
3134
3135 #ifdef _WIN32
3136   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3137     /* the user wants a console or the application will terminate immediately */
3138     create_console();
3139   }
3140   if (has_console) {
3141     /* For some unknown reason, the above doesn't appear to actually cause
3142        anything to be sent to the standard output, so we'll just splat the
3143        message out directly, just to make sure it gets out. */
3144 #endif
3145     switch(log_level & G_LOG_LEVEL_MASK) {
3146     case G_LOG_LEVEL_ERROR:
3147         level = "Err ";
3148         break;
3149     case G_LOG_LEVEL_CRITICAL:
3150         level = "Crit";
3151         break;
3152     case G_LOG_LEVEL_WARNING:
3153         level = "Warn";
3154         break;
3155     case G_LOG_LEVEL_MESSAGE:
3156         level = "Msg ";
3157         break;
3158     case G_LOG_LEVEL_INFO:
3159         level = "Info";
3160         break;
3161     case G_LOG_LEVEL_DEBUG:
3162         level = "Dbg ";
3163         break;
3164     default:
3165         fprintf(stderr, "unknown log_level %u\n", log_level);
3166         level = NULL;
3167         g_assert_not_reached();
3168     }
3169
3170     /* create a "timestamp" */
3171     time(&curr);
3172     today = localtime(&curr);
3173
3174     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3175             today->tm_hour, today->tm_min, today->tm_sec,
3176             log_domain != NULL ? log_domain : "",
3177             level, message);
3178 #ifdef _WIN32
3179     if(log_level & G_LOG_LEVEL_ERROR) {
3180         /* wait for a key press before the following error handler will terminate the program
3181            this way the user at least can read the error message */
3182         printf("\n\nPress any key to exit\n");
3183         _getch();
3184     }
3185   } else {
3186     /* XXX - on UN*X, should we just use g_log_default_handler()?
3187        We want the error messages to go to the standard output;
3188        on Mac OS X, that will cause them to show up in various
3189        per-user logs accessible through Console (details depend
3190        on whether you're running 10.0 through 10.4 or running
3191        10.5 and later), and, on other UN*X desktop environments,
3192        if they don't show up in some form of console log, that's
3193        a deficiency in that desktop environment.  (Too bad
3194        Windows doesn't set the standard output and error for
3195        GUI apps to something that shows up in such a log.) */
3196     g_log_default_handler(log_domain, log_level, message, user_data);
3197   }
3198 #endif
3199 }
3200
3201
3202 /*
3203  * Helper for main_widgets_rearrange()
3204  */
3205 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3206     gtk_container_remove(GTK_CONTAINER(data), widget);
3207 }
3208
3209 static GtkWidget *main_widget_layout(gint layout_content)
3210 {
3211     switch(layout_content) {
3212     case(layout_pane_content_none):
3213         return NULL;
3214     case(layout_pane_content_plist):
3215         return pkt_scrollw;
3216     case(layout_pane_content_pdetails):
3217         return tv_scrollw;
3218     case(layout_pane_content_pbytes):
3219         return byte_nb_ptr_gbl;
3220     default:
3221         g_assert_not_reached();
3222         return NULL;
3223     }
3224 }
3225
3226
3227 /*
3228  * Rearrange the main window widgets
3229  */
3230 void main_widgets_rearrange(void) {
3231     GtkWidget *first_pane_widget1, *first_pane_widget2;
3232     GtkWidget *second_pane_widget1, *second_pane_widget2;
3233     gboolean split_top_left;
3234
3235     /* be a bit faster */
3236     gtk_widget_hide(main_vbox);
3237
3238     /* be sure we don't lose a widget while rearranging */
3239     g_object_ref(G_OBJECT(menubar));
3240     g_object_ref(G_OBJECT(main_tb));
3241     g_object_ref(G_OBJECT(filter_tb));
3242 #ifdef HAVE_AIRPCAP
3243     g_object_ref(G_OBJECT(airpcap_tb));
3244 #endif
3245     g_object_ref(G_OBJECT(pkt_scrollw));
3246     g_object_ref(G_OBJECT(tv_scrollw));
3247     g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3248     g_object_ref(G_OBJECT(statusbar));
3249     g_object_ref(G_OBJECT(main_pane_v1));
3250     g_object_ref(G_OBJECT(main_pane_v2));
3251     g_object_ref(G_OBJECT(main_pane_h1));
3252     g_object_ref(G_OBJECT(main_pane_h2));
3253     g_object_ref(G_OBJECT(welcome_pane));
3254
3255     /* empty all containers participating */
3256     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3257     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3258     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3259     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3260     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3261
3262     statusbar_widgets_emptying(statusbar);
3263
3264     /* add the menubar always at the top */
3265     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3266
3267     /* main toolbar */
3268     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3269
3270     /* filter toolbar in toolbar area */
3271     if (!prefs.filter_toolbar_show_in_statusbar) {
3272         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3273     }
3274
3275 #ifdef HAVE_AIRPCAP
3276     /* airpcap toolbar */
3277     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3278 #endif
3279
3280     /* fill the main layout panes */
3281     switch(prefs.gui_layout_type) {
3282     case(layout_type_5):
3283         main_first_pane  = main_pane_v1;
3284         main_second_pane = main_pane_v2;
3285         split_top_left = FALSE;
3286         break;
3287     case(layout_type_2):
3288         main_first_pane  = main_pane_v1;
3289         main_second_pane = main_pane_h1;
3290         split_top_left = FALSE;
3291         break;
3292     case(layout_type_1):
3293         main_first_pane  = main_pane_v1;
3294         main_second_pane = main_pane_h1;
3295         split_top_left = TRUE;
3296         break;
3297     case(layout_type_4):
3298         main_first_pane  = main_pane_h1;
3299         main_second_pane = main_pane_v1;
3300         split_top_left = FALSE;
3301         break;
3302     case(layout_type_3):
3303         main_first_pane  = main_pane_h1;
3304         main_second_pane = main_pane_v1;
3305         split_top_left = TRUE;
3306         break;
3307     case(layout_type_6):
3308         main_first_pane  = main_pane_h1;
3309         main_second_pane = main_pane_h2;
3310         split_top_left = FALSE;
3311         break;
3312     default:
3313         main_first_pane = NULL;
3314         main_second_pane = NULL;
3315         split_top_left = FALSE;
3316         g_assert_not_reached();
3317     }
3318     if (split_top_left) {
3319         first_pane_widget1 = main_second_pane;
3320         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3321         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3322         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3323     } else {
3324         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3325         first_pane_widget2 = main_second_pane;
3326         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3327         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3328     }
3329     if (first_pane_widget1 != NULL)
3330         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3331     if (first_pane_widget2 != NULL)
3332         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3333     if (second_pane_widget1 != NULL)
3334         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3335     if (second_pane_widget2 != NULL)
3336         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3337
3338     gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3339
3340     /* welcome pane */
3341     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3342
3343     /* statusbar */
3344     gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3345
3346     /* filter toolbar in statusbar hbox */
3347     if (prefs.filter_toolbar_show_in_statusbar) {
3348         gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3349     }
3350
3351 #ifdef HAVE_AIRPCAP
3352     /* airpcap toolbar */
3353     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3354 #endif
3355
3356     /* statusbar widgets */
3357     statusbar_widgets_pack(statusbar);
3358
3359     /* hide widgets on users recent settings */
3360     main_widgets_show_or_hide();
3361
3362     gtk_widget_show(main_vbox);
3363 }
3364
3365 static void
3366 is_widget_visible(GtkWidget *widget, gpointer data)
3367 {
3368     gboolean *is_visible = data;
3369
3370     if (!*is_visible) {
3371         if (GTK_WIDGET_VISIBLE(widget))
3372             *is_visible = TRUE;
3373     }
3374 }
3375
3376
3377 void
3378 main_widgets_show_or_hide(void)
3379 {
3380     gboolean main_second_pane_show;
3381
3382     if (recent.main_toolbar_show) {
3383         gtk_widget_show(main_tb);
3384     } else {
3385         gtk_widget_hide(main_tb);
3386     }
3387
3388     statusbar_widgets_show_or_hide(statusbar);
3389
3390     if (recent.filter_toolbar_show) {
3391         gtk_widget_show(filter_tb);
3392     } else {
3393         gtk_widget_hide(filter_tb);
3394     }
3395
3396 #ifdef HAVE_AIRPCAP
3397     if (recent.airpcap_toolbar_show) {
3398         gtk_widget_show(airpcap_tb);
3399     } else {
3400         gtk_widget_hide(airpcap_tb);
3401     }
3402 #endif
3403
3404     if (recent.packet_list_show && have_capture_file) {
3405         gtk_widget_show(pkt_scrollw);
3406     } else {
3407         gtk_widget_hide(pkt_scrollw);
3408     }
3409
3410     if (recent.tree_view_show && have_capture_file) {
3411         gtk_widget_show(tv_scrollw);
3412     } else {
3413         gtk_widget_hide(tv_scrollw);
3414     }
3415
3416     if (recent.byte_view_show && have_capture_file) {
3417         gtk_widget_show(byte_nb_ptr_gbl);
3418     } else {
3419         gtk_widget_hide(byte_nb_ptr_gbl);
3420     }
3421
3422     if (have_capture_file) {
3423         gtk_widget_show(main_first_pane);
3424     } else {
3425         gtk_widget_hide(main_first_pane);
3426     }
3427
3428     /*
3429      * Is anything in "main_second_pane" visible?
3430      * If so, show it, otherwise hide it.
3431      */
3432     main_second_pane_show = FALSE;
3433     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3434                           &main_second_pane_show);
3435     if (main_second_pane_show) {
3436         gtk_widget_show(main_second_pane);
3437     } else {
3438         gtk_widget_hide(main_second_pane);
3439     }
3440
3441     if (!have_capture_file) {
3442         if(welcome_pane) {
3443             gtk_widget_show(welcome_pane);
3444         }
3445     } else {
3446         gtk_widget_hide(welcome_pane);
3447     }
3448
3449     /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3450 #ifndef NEW_PACKET_LIST
3451     packet_list_freeze ();
3452     packet_list_thaw ();
3453 #endif
3454 }
3455
3456
3457 /* called, when the window state changes (minimized, maximized, ...) */
3458 static int
3459 window_state_event_cb (GtkWidget *widget _U_,
3460                        GdkEvent *event,
3461                        gpointer  data _U_)
3462 {
3463     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3464
3465     if( (event->type) == (GDK_WINDOW_STATE)) {
3466         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3467             /* we might have dialogs popped up while we where iconified,
3468                show em now */
3469             display_queued_messages();
3470         }
3471     }
3472     return FALSE;
3473 }
3474
3475
3476
3477 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3478 static int
3479 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3480 {
3481     if (event->keyval == GDK_F8) {
3482 #ifdef NEW_PACKET_LIST
3483         new_packet_list_next();
3484 #else
3485         packet_list_next();
3486 #endif
3487         return TRUE;
3488     } else if (event->keyval == GDK_F7) {
3489 #ifdef NEW_PACKET_LIST
3490         new_packet_list_prev();
3491 #else
3492         packet_list_prev();
3493 #endif
3494         return TRUE;
3495     } else if (event->state & NO_SHIFT_MOD_MASK) {
3496         return FALSE; /* Skip control, alt, and other modifiers */
3497     /*
3498      * A comment in gdkkeysyms.h says that it's autogenerated from
3499      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
3500      * don't explicitly say so, isprint() should work as expected
3501      * for values < 127.
3502      */
3503     } else if (isascii(event->keyval) && isprint(event->keyval)) {
3504         /* Forward the keypress on to the display filter entry */
3505         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3506             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3507             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3508         }
3509         return FALSE;
3510     }
3511     return FALSE;
3512 }
3513
3514 static void
3515 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3516 {
3517     GtkAccelGroup *accel;
3518     gchar         *title;
3519
3520     /* use user-defined title if preference is set */
3521     title = create_user_window_title("The Wireshark Network Analyzer");
3522
3523     /* Main window */
3524     top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3525     g_free(title);
3526
3527     gtk_widget_set_name(top_level, "main window");
3528     g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3529                    NULL);
3530     g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3531                          G_CALLBACK(window_state_event_cb), NULL);
3532     g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3533                          G_CALLBACK(top_level_key_pressed_cb), NULL );
3534
3535     /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3536     main_vbox = gtk_vbox_new(FALSE, 1);
3537     gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3538     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3539     gtk_widget_show(main_vbox);
3540
3541     /* Menu bar */
3542     menubar = main_menu_new(&accel);
3543
3544 #ifdef HAVE_IGE_MAC_INTEGRATION
3545     /* MacOS X native menus are created and displayed by main_menu_new() */
3546     if(!prefs_p->gui_macosx_style) {
3547 #endif
3548     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3549     gtk_widget_show(menubar);
3550 #ifdef HAVE_IGE_MAC_INTEGRATION
3551     }
3552 #endif
3553
3554     /* Main Toolbar */
3555     main_tb = toolbar_new();
3556     gtk_widget_show (main_tb);
3557
3558     /* Filter toolbar */
3559     filter_tb = filter_toolbar_new();
3560
3561     /* Packet list */
3562 #ifdef NEW_PACKET_LIST
3563     pkt_scrollw = new_packet_list_create();
3564     gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3565     gtk_widget_show_all(pkt_scrollw);
3566 #else
3567     pkt_scrollw = packet_list_new(prefs_p);
3568     gtk_widget_set_size_request(packet_list, -1, pl_size);
3569     gtk_widget_show(pkt_scrollw);
3570 #endif
3571
3572     /* Tree view */
3573     tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3574     gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3575     gtk_widget_show(tv_scrollw);
3576
3577     g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3578                    "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3579     g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3580                    g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3581     gtk_widget_show(tree_view_gbl);
3582
3583     /* Byte view. */
3584     byte_nb_ptr_gbl = byte_view_new();
3585     gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3586     gtk_widget_show(byte_nb_ptr_gbl);
3587
3588     g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3589                    g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3590
3591     /* Panes for the packet list, tree, and byte view */
3592     main_pane_v1 = gtk_vpaned_new();
3593     gtk_widget_show(main_pane_v1);
3594     main_pane_v2 = gtk_vpaned_new();
3595     gtk_widget_show(main_pane_v2);
3596     main_pane_h1 = gtk_hpaned_new();
3597     gtk_widget_show(main_pane_h1);
3598     main_pane_h2 = gtk_hpaned_new();
3599     gtk_widget_show(main_pane_h2);
3600 #ifdef HAVE_AIRPCAP
3601     airpcap_tb = airpcap_toolbar_new();
3602     gtk_widget_show(airpcap_tb);
3603 #endif
3604     /* status bar */
3605     statusbar = statusbar_new();
3606     gtk_widget_show(statusbar);
3607
3608     /* Pane for the welcome screen */
3609     welcome_pane = welcome_new();
3610     gtk_widget_show(welcome_pane);
3611 }
3612
3613 static void
3614 show_main_window(gboolean doing_work)
3615 {
3616   main_set_for_capture_file(doing_work);
3617
3618   /*** we have finished all init things, show the main window ***/
3619   gtk_widget_show(top_level);
3620
3621   /* the window can be maximized only, if it's visible, so do it after show! */
3622   main_load_window_geometry(top_level);
3623
3624   /* process all pending GUI events before continue */
3625   while (gtk_events_pending()) gtk_main_iteration();
3626
3627   /* Pop up any queued-up alert boxes. */
3628   display_queued_messages();
3629
3630   /* Move the main window to the front, in case it isn't already there */
3631   gdk_window_raise(top_level->window);
3632
3633 #ifdef HAVE_AIRPCAP
3634   airpcap_toolbar_show(airpcap_tb);
3635 #endif /* HAVE_AIRPCAP */
3636 }
3637
3638 /* Fill in capture options with values from the preferences */
3639 void
3640 prefs_to_capture_opts(void)
3641 {
3642 #ifdef HAVE_LIBPCAP
3643   /* Set promiscuous mode from the preferences setting. */
3644   /* the same applies to other preferences settings as well. */
3645     global_capture_opts.promisc_mode   = prefs.capture_prom_mode;
3646     global_capture_opts.use_pcapng     = prefs.capture_pcap_ng;
3647     global_capture_opts.show_info      = prefs.capture_show_info;
3648     global_capture_opts.real_time_mode = prefs.capture_real_time;
3649     auto_scroll_live                   = prefs.capture_auto_scroll;
3650 #endif /* HAVE_LIBPCAP */
3651
3652   /* Set the name resolution code's flags from the preferences. */
3653     g_resolv_flags = prefs.name_resolve;
3654 }
3655
3656
3657 /* Change configuration profile */
3658 void change_configuration_profile (const gchar *profile_name)
3659 {
3660    char  *gdp_path, *dp_path;
3661    char  *rf_path;
3662    int    rf_open_errno;
3663
3664    /* First check if profile exists */
3665    if (!profile_exists(profile_name)) {
3666      return;
3667    }
3668
3669    /* Get the current geometry, before writing it to disk */
3670    main_save_window_geometry(top_level);
3671
3672    if (profile_exists(get_profile_name())) {
3673      /* Write recent file for profile we are leaving, if it still exists */
3674      write_profile_recent();
3675    }
3676
3677    /* Set profile name and update the status bar */
3678    set_profile_name (profile_name);
3679    profile_bar_update ();
3680
3681    /* Reset current preferences and apply the new */
3682    prefs_reset();
3683    menu_prefs_reset();
3684
3685    (void) read_configuration_files (&gdp_path, &dp_path);
3686
3687    recent_read_profile_static(&rf_path, &rf_open_errno);
3688    if (rf_path != NULL && rf_open_errno != 0) {
3689      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3690                   "Could not open common recent file\n\"%s\": %s.",
3691                   rf_path, strerror(rf_open_errno));
3692    }
3693    timestamp_set_type (recent.gui_time_format);
3694    timestamp_set_seconds_type (recent.gui_seconds_format);
3695    color_filters_enable(recent.packet_list_colorize);
3696
3697    prefs_to_capture_opts();
3698    prefs_apply_all();
3699
3700    /* Update window view and redraw the toolbar */
3701    update_main_window_name();
3702    toolbar_redraw_all();
3703
3704    /* Enable all protocols and disable from the disabled list */
3705    proto_enable_all();
3706    if (gdp_path == NULL && dp_path == NULL) {
3707      set_disabled_protos_list();
3708    }
3709
3710    /* Reload color filters */
3711    color_filters_reload();
3712
3713    /* Reload list of interfaces on welcome page */
3714    welcome_if_panel_reload();
3715
3716    /* Recreate the packet list according to new preferences */
3717 #ifdef NEW_PACKET_LIST
3718    new_packet_list_recreate ();
3719 #else
3720    packet_list_recreate ();
3721 #endif
3722    cfile.cinfo.columns_changed = FALSE; /* Reset value */
3723    user_font_apply();
3724
3725    /* Update menus with new recent values */
3726    menu_recent_read_finished();
3727
3728    /* Reload pane geometry, must be done after recreating the list */
3729    main_pane_load_window_geometry();
3730 }
3731
3732 /** redissect packets and update UI */
3733 void redissect_packets(void)
3734 {
3735     cf_redissect_packets(&cfile);
3736     status_expert_update();
3737 }