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