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