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