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