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