Move the get-runtime-version stuff back outside of #ifdef WIN32.
[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 #endif  /* _WIN32 */
2295
2296   /* Assemble the compile-time version information string */
2297   comp_info_str = g_string_new("Compiled ");
2298
2299   get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2300
2301   /* Assemble the run-time version information string */
2302   runtime_info_str = g_string_new("Running ");
2303   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2304
2305 #ifdef _WIN32
2306   ws_add_crash_info(PACKAGE " " VERSION "%s\n"
2307          "\n"
2308          "%s"
2309          "\n"
2310          "%s",
2311       wireshark_svnversion, comp_info_str->str, runtime_info_str->str);
2312
2313   /* Start windows sockets */
2314   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2315 #endif  /* _WIN32 */
2316
2317   profile_store_persconffiles (TRUE);
2318
2319   /* Read the profile independent recent file.  We have to do this here so we can */
2320   /* set the profile before it can be set from the command line parameterts */
2321   recent_read_static(&rf_path, &rf_open_errno);
2322   if (rf_path != NULL && rf_open_errno != 0) {
2323     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2324                   "Could not open common recent file\n\"%s\": %s.",
2325                   rf_path, g_strerror(rf_open_errno));
2326   }
2327
2328   /* "pre-scan" the command line parameters, if we have "console only"
2329      parameters.  We do this so we don't start GTK+ if we're only showing
2330      command-line help or version information.
2331
2332      XXX - this pre-scan is done before we start GTK+, so we haven't
2333      run gtk_init() on the arguments.  That means that GTK+ arguments
2334      have not been removed from the argument list; those arguments
2335      begin with "--", and will be treated as an error by getopt().
2336
2337      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2338      error messages. */
2339   opterr = 0;
2340   optind_initial = optind;
2341   while ((opt = getopt(argc, argv, optstring)) != -1) {
2342     switch (opt) {
2343       case 'C':        /* Configuration Profile */
2344         if (profile_exists (optarg, FALSE)) {
2345           set_profile_name (optarg);
2346         } else {
2347           cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2348           exit(1);
2349         }
2350         break;
2351       case 'D':        /* Print a list of capture devices and exit */
2352 #ifdef HAVE_LIBPCAP
2353         if_list = capture_interface_list(&err, &err_str);
2354         if (if_list == NULL) {
2355           switch (err) {
2356           case CANT_GET_INTERFACE_LIST:
2357           case DONT_HAVE_PCAP:
2358             cmdarg_err("%s", err_str);
2359             g_free(err_str);
2360             break;
2361
2362           case NO_INTERFACES_FOUND:
2363             cmdarg_err("There are no interfaces on which a capture can be done");
2364             break;
2365           }
2366           exit(2);
2367         }
2368         capture_opts_print_interfaces(if_list);
2369         free_interface_list(if_list);
2370         exit(0);
2371 #else
2372         capture_option_specified = TRUE;
2373         arg_error = TRUE;
2374 #endif
2375         break;
2376       case 'h':        /* Print help and exit */
2377         print_usage(TRUE);
2378         exit(0);
2379         break;
2380 #ifdef _WIN32
2381       case 'i':
2382         if (strcmp(optarg, "-") == 0)
2383           set_stdin_capture(TRUE);
2384         break;
2385 #endif
2386       case 'P':        /* Path settings - change these before the Preferences and alike are processed */
2387         status = filesystem_opt(opt, optarg);
2388         if(status != 0) {
2389             cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2390             exit(status);
2391         }
2392         break;
2393       case 'v':        /* Show version and exit */
2394         show_version();
2395         exit(0);
2396         break;
2397       case 'X':
2398         /*
2399          *  Extension command line options have to be processed before
2400          *  we call epan_init() as they are supposed to be used by dissectors
2401          *  or taps very early in the registration process.
2402          */
2403         ex_opt_add(optarg);
2404         break;
2405       case '?':        /* Ignore errors - the "real" scan will catch them. */
2406         break;
2407     }
2408   }
2409
2410   /* Init the "Open file" dialog directory */
2411   /* (do this after the path settings are processed) */
2412
2413   /* Read the profile dependent (static part) of the recent file. */
2414   /* Only the static part of it will be read, as we don't have the gui now to fill the */
2415   /* recent lists which is done in the dynamic part. */
2416   /* We have to do this already here, so command line parameters can overwrite these values. */
2417   recent_read_profile_static(&rf_path, &rf_open_errno);
2418   if (rf_path != NULL && rf_open_errno != 0) {
2419     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2420                   "Could not open recent file\n\"%s\": %s.",
2421                   rf_path, g_strerror(rf_open_errno));
2422   }
2423
2424   if (recent.gui_fileopen_remembered_dir &&
2425       test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2426     set_last_open_dir(recent.gui_fileopen_remembered_dir);
2427   } else {
2428     set_last_open_dir(get_persdatafile_dir());
2429   }
2430
2431   /* Set getopt index back to initial value, so it will start with the
2432      first command line parameter again.  Also reset opterr to 1, so that
2433      error messages are printed by getopt().
2434
2435      XXX - this seems to work on most platforms, but time will tell.
2436      The Single UNIX Specification says "The getopt() function need
2437      not be reentrant", so this isn't guaranteed to work.  The Mac
2438      OS X 10.4[.x] getopt() man page says
2439
2440        In order to use getopt() to evaluate multiple sets of arguments, or to
2441        evaluate a single set of arguments multiple times, the variable optreset
2442        must be set to 1 before the second and each additional set of calls to
2443        getopt(), and the variable optind must be reinitialized.
2444
2445            ...
2446
2447        The optreset variable was added to make it possible to call the getopt()
2448        function multiple times.  This is an extension to the IEEE Std 1003.2
2449        (``POSIX.2'') specification.
2450
2451      which I think comes from one of the other BSDs.
2452
2453      XXX - if we want to control all the command-line option errors, so
2454      that we can display them where we choose (e.g., in a window), we'd
2455      want to leave opterr as 0, and produce our own messages using optopt.
2456      We'd have to check the value of optopt to see if it's a valid option
2457      letter, in which case *presumably* the error is "this option requires
2458      an argument but none was specified", or not a valid option letter,
2459      in which case *presumably* the error is "this option isn't valid".
2460      Some versions of getopt() let you supply a option string beginning
2461      with ':', which means that getopt() will return ':' rather than '?'
2462      for "this option requires an argument but none was specified", but
2463      not all do. */
2464   optind = optind_initial;
2465   opterr = 1;
2466
2467 #if !GLIB_CHECK_VERSION(2,31,0)
2468   g_thread_init(NULL);
2469 #endif
2470
2471   /* Set the current locale according to the program environment.
2472    * We haven't localized anything, but some GTK widgets are localized
2473    * (the file selection dialogue, for example).
2474    * This also sets the C-language locale to the native environment. */
2475   setlocale (LC_ALL, "");
2476
2477   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2478   gtk_init (&argc, &argv);
2479
2480   cf_callback_add(main_cf_callback, NULL);
2481 #ifdef HAVE_LIBPCAP
2482   capture_callback_add(main_capture_callback, NULL);
2483 #endif
2484   cf_callback_add(statusbar_cf_callback, NULL);
2485 #ifdef HAVE_LIBPCAP
2486   capture_callback_add(statusbar_capture_callback, NULL);
2487 #endif
2488
2489   /* Arrange that if we have no console window, and a GLib message logging
2490      routine is called to log a message, we pop up a console window.
2491
2492      We do that by inserting our own handler for all messages logged
2493      to the default domain; that handler pops up a console if necessary,
2494      and then calls the default handler. */
2495
2496   /* We might want to have component specific log levels later ... */
2497
2498   log_flags =
2499             G_LOG_LEVEL_ERROR|
2500             G_LOG_LEVEL_CRITICAL|
2501             G_LOG_LEVEL_WARNING|
2502             G_LOG_LEVEL_MESSAGE|
2503             G_LOG_LEVEL_INFO|
2504             G_LOG_LEVEL_DEBUG|
2505             G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2506
2507   g_log_set_handler(NULL,
2508             log_flags,
2509             console_log_handler, NULL /* user_data */);
2510   g_log_set_handler(LOG_DOMAIN_MAIN,
2511             log_flags,
2512             console_log_handler, NULL /* user_data */);
2513
2514 #ifdef HAVE_LIBPCAP
2515   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2516             log_flags,
2517             console_log_handler, NULL /* user_data */);
2518   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2519             log_flags,
2520             console_log_handler, NULL /* user_data */);
2521
2522   /* Set the initial values in the capture options. This might be overwritten
2523      by preference settings and then again by the command line parameters. */
2524   capture_opts_init(&global_capture_opts, &cfile);
2525 #endif
2526
2527   /* Initialize whatever we need to allocate colors for GTK+ */
2528   colors_init();
2529
2530   /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2531   filter = get_conn_cfilter();
2532   if ( *filter != '\0' ) {
2533     info_update_freq = 1000;  /* Milliseconds */
2534   }
2535
2536   /* We won't come till here, if we had a "console only" command line parameter. */
2537   splash_win = splash_new("Loading Wireshark ...");
2538   if (init_progfile_dir_error != NULL) {
2539     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2540         "Can't get pathname of Wireshark: %s.\n"
2541         "It won't be possible to capture traffic.\n"
2542         "Report this to the Wireshark developers.",
2543         init_progfile_dir_error);
2544     g_free(init_progfile_dir_error);
2545   }
2546
2547   splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2548
2549   /* Register all dissectors; we must do this before checking for the
2550      "-G" flag, as the "-G" flag dumps information registered by the
2551      dissectors, and we must do it before we read the preferences, in
2552      case any dissectors register preferences. */
2553   epan_init(register_all_protocols,register_all_protocol_handoffs,
2554             splash_update, (gpointer) splash_win,
2555             failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2556             write_failure_alert_box);
2557
2558   splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2559
2560   /* Register all tap listeners; we do this before we parse the arguments,
2561      as the "-z" argument can specify a registered tap. */
2562
2563   /* we register the plugin taps before the other taps because
2564      stats_tree taps plugins will be registered as tap listeners
2565      by stats_tree_stat.c and need to registered before that */
2566
2567 #ifdef HAVE_PLUGINS
2568   register_all_plugin_tap_listeners();
2569 #endif
2570
2571   register_all_tap_listeners();
2572
2573   splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2574
2575   prefs_p = read_configuration_files (&gdp_path, &dp_path);
2576   /* Removed thread code:
2577    * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
2578    */
2579
2580   /* this is to keep tap extensions updating once every 3 seconds */
2581   tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2582
2583   splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2584   proto_help_init();
2585   cap_file_init(&cfile);
2586
2587   /* Fill in capture options with values from the preferences */
2588   prefs_to_capture_opts();
2589
2590 /*#ifdef HAVE_LIBPCAP
2591   fill_in_local_interfaces();
2592 #endif*/
2593   /* Now get our args */
2594   while ((opt = getopt(argc, argv, optstring)) != -1) {
2595     switch (opt) {
2596       /*** capture option specific ***/
2597       case 'a':        /* autostop criteria */
2598       case 'b':        /* Ringbuffer option */
2599       case 'c':        /* Capture xxx packets */
2600       case 'f':        /* capture filter */
2601       case 'k':        /* Start capture immediately */
2602       case 'H':        /* Hide capture info dialog box */
2603       case 'p':        /* Don't capture in promiscuous mode */
2604       case 'i':        /* Use interface x */
2605 #ifdef HAVE_PCAP_CREATE
2606       case 'I':        /* Capture in monitor mode, if available */
2607 #endif
2608 #ifdef HAVE_PCAP_REMOTE
2609       case 'A':        /* Authentication */
2610 #endif
2611       case 's':        /* Set the snapshot (capture) length */
2612       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2613       case 'w':        /* Write to capture file xxx */
2614       case 'y':        /* Set the pcap data link type */
2615 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2616       case 'B':        /* Buffer size */
2617 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2618 #ifdef HAVE_LIBPCAP
2619         status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2620                                       &start_capture);
2621         if(status != 0) {
2622             exit(status);
2623         }
2624 #else
2625         capture_option_specified = TRUE;
2626         arg_error = TRUE;
2627 #endif
2628         break;
2629
2630 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2631       case 'K':        /* Kerberos keytab file */
2632         read_keytab_file(optarg);
2633         break;
2634 #endif
2635
2636       /*** all non capture option specific ***/
2637       case 'C':
2638         /* Configuration profile settings were already processed just ignore them this time*/
2639         break;
2640       case 'd':
2641         dfilter = optarg;
2642         break;
2643       case 'j':        /* Search backwards for a matching packet from filter in option J */
2644         jump_backwards = TRUE;
2645         break;
2646       case 'g':        /* Go to packet with the given packet number */
2647         go_to_packet = get_positive_int(optarg, "go to packet");
2648         break;
2649       case 'J':        /* Jump to the first packet which matches the filter criteria */
2650         jfilter = optarg;
2651         break;
2652       case 'l':        /* Automatic scrolling in live capture mode */
2653 #ifdef HAVE_LIBPCAP
2654         auto_scroll_live = TRUE;
2655 #else
2656         capture_option_specified = TRUE;
2657         arg_error = TRUE;
2658 #endif
2659         break;
2660       case 'L':        /* Print list of link-layer types and exit */
2661 #ifdef HAVE_LIBPCAP
2662         list_link_layer_types = TRUE;
2663 #else
2664         capture_option_specified = TRUE;
2665         arg_error = TRUE;
2666 #endif
2667         break;
2668       case 'm':        /* Fixed-width font for the display */
2669         g_free(prefs_p->gui_gtk2_font_name);
2670         prefs_p->gui_gtk2_font_name = g_strdup(optarg);
2671         break;
2672       case 'n':        /* No name resolution */
2673         gbl_resolv_flags.mac_name = FALSE;
2674         gbl_resolv_flags.network_name = FALSE;
2675         gbl_resolv_flags.transport_name = FALSE;
2676         gbl_resolv_flags.concurrent_dns = FALSE;
2677         break;
2678       case 'N':        /* Select what types of addresses/port #s to resolve */
2679         badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2680         if (badopt != '\0') {
2681           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2682             badopt);
2683           exit(1);
2684         }
2685         break;
2686       case 'o':        /* Override preference from command line */
2687         switch (prefs_set_pref(optarg)) {
2688         case PREFS_SET_OK:
2689           break;
2690         case PREFS_SET_SYNTAX_ERR:
2691           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2692           exit(1);
2693           break;
2694         case PREFS_SET_NO_SUCH_PREF:
2695           /* not a preference, might be a recent setting */
2696           switch (recent_set_arg(optarg)) {
2697             case PREFS_SET_OK:
2698               break;
2699             case PREFS_SET_SYNTAX_ERR:
2700               /* shouldn't happen, checked already above */
2701               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2702               exit(1);
2703               break;
2704             case PREFS_SET_NO_SUCH_PREF:
2705             case PREFS_SET_OBSOLETE:
2706               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2707                 optarg);
2708               exit(1);
2709               break;
2710             default:
2711               g_assert_not_reached();
2712             }
2713           break;
2714         case PREFS_SET_OBSOLETE:
2715           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2716             optarg);
2717           exit(1);
2718           break;
2719         default:
2720           g_assert_not_reached();
2721         }
2722         break;
2723       case 'P':
2724         /* Path settings were already processed just ignore them this time*/
2725         break;
2726       case 'r':        /* Read capture file xxx */
2727         /* We may set "last_open_dir" to "cf_name", and if we change
2728         "last_open_dir" later, we free the old value, so we have to
2729         set "cf_name" to something that's been allocated. */
2730         cf_name = g_strdup(optarg);
2731         break;
2732       case 'R':        /* Read file filter */
2733         rfilter = optarg;
2734         break;
2735       case 't':        /* Time stamp type */
2736         if (strcmp(optarg, "r") == 0)
2737           timestamp_set_type(TS_RELATIVE);
2738         else if (strcmp(optarg, "a") == 0)
2739           timestamp_set_type(TS_ABSOLUTE);
2740         else if (strcmp(optarg, "ad") == 0)
2741           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2742         else if (strcmp(optarg, "d") == 0)
2743           timestamp_set_type(TS_DELTA);
2744         else if (strcmp(optarg, "dd") == 0)
2745           timestamp_set_type(TS_DELTA_DIS);
2746         else if (strcmp(optarg, "e") == 0)
2747           timestamp_set_type(TS_EPOCH);
2748         else if (strcmp(optarg, "u") == 0)
2749           timestamp_set_type(TS_UTC);
2750         else if (strcmp(optarg, "ud") == 0)
2751           timestamp_set_type(TS_UTC_WITH_DATE);
2752         else {
2753           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2754           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2755           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2756           exit(1);
2757         }
2758         break;
2759       case 'u':        /* Seconds type */
2760         if (strcmp(optarg, "s") == 0)
2761           timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2762         else if (strcmp(optarg, "hms") == 0)
2763           timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2764         else {
2765           cmdarg_err("Invalid seconds type \"%s\"", optarg);
2766           cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2767           exit(1);
2768         }
2769         break;
2770       case 'X':
2771           /* ext ops were already processed just ignore them this time*/
2772           break;
2773       case 'z':
2774         /* We won't call the init function for the stat this soon
2775            as it would disallow MATE's fields (which are registered
2776            by the preferences set callback) from being used as
2777            part of a tap filter.  Instead, we just add the argument
2778            to a list of stat arguments. */
2779         if (!process_stat_cmd_arg(optarg)) {
2780           cmdarg_err("Invalid -z argument.");
2781           cmdarg_err_cont("  -z argument must be one of :");
2782           list_stat_cmd_args();
2783           exit(1);
2784         }
2785         break;
2786       default:
2787       case '?':        /* Bad flag - print usage message */
2788         arg_error = TRUE;
2789         break;
2790     }
2791   }
2792   if (!arg_error) {
2793     argc -= optind;
2794     argv += optind;
2795     if (argc >= 1) {
2796       if (cf_name != NULL) {
2797         /*
2798          * Input file name specified with "-r" *and* specified as a regular
2799          * command-line argument.
2800          */
2801         cmdarg_err("File name specified both with -r and regular argument");
2802         arg_error = TRUE;
2803       } else {
2804         /*
2805          * Input file name not specified with "-r", and a command-line argument
2806          * was specified; treat it as the input file name.
2807          *
2808          * Yes, this is different from tshark, where non-flag command-line
2809          * arguments are a filter, but this works better on GUI desktops
2810          * where a command can be specified to be run to open a particular
2811          * file - yes, you could have "-r" as the last part of the command,
2812          * but that's a bit ugly.
2813          */
2814 #ifndef HAVE_GTKOSXAPPLICATION
2815         /*
2816          * For GTK+ Mac Integration, file name passed as free argument passed
2817          * through grag-and-drop and opened twice sometimes causing crashes.
2818          * Subject to report to GTK+ MAC.
2819          */
2820         cf_name = g_strdup(argv[0]);
2821 #endif
2822       }
2823       argc--;
2824       argv++;
2825     }
2826
2827     if (argc != 0) {
2828       /*
2829        * Extra command line arguments were specified; complain.
2830        */
2831       cmdarg_err("Invalid argument: %s", argv[0]);
2832       arg_error = TRUE;
2833     }
2834   }
2835   if (arg_error) {
2836 #ifndef HAVE_LIBPCAP
2837     if (capture_option_specified) {
2838       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2839     }
2840 #endif
2841     print_usage(FALSE);
2842     exit(1);
2843   }
2844
2845 #ifdef HAVE_LIBPCAP
2846   fill_in_local_interfaces();
2847   if (start_capture && list_link_layer_types) {
2848     /* Specifying *both* is bogus. */
2849     cmdarg_err("You can't specify both -L and a live capture.");
2850     exit(1);
2851   }
2852
2853   if (list_link_layer_types) {
2854     /* We're supposed to list the link-layer types for an interface;
2855        did the user also specify a capture file to be read? */
2856     if (cf_name) {
2857       /* Yes - that's bogus. */
2858       cmdarg_err("You can't specify -L and a capture file to be read.");
2859       exit(1);
2860     }
2861     /* No - did they specify a ring buffer option? */
2862     if (global_capture_opts.multi_files_on) {
2863       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2864       exit(1);
2865     }
2866   } else {
2867     /* We're supposed to do a live capture; did the user also specify
2868        a capture file to be read? */
2869     if (start_capture && cf_name) {
2870       /* Yes - that's bogus. */
2871       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2872       exit(1);
2873     }
2874
2875     /* No - was the ring buffer option specified and, if so, does it make
2876        sense? */
2877     if (global_capture_opts.multi_files_on) {
2878       /* Ring buffer works only under certain conditions:
2879       a) ring buffer does not work with temporary files;
2880       b) real_time_mode and multi_files_on are mutually exclusive -
2881          real_time_mode takes precedence;
2882       c) it makes no sense to enable the ring buffer if the maximum
2883          file size is set to "infinite". */
2884       if (global_capture_opts.save_file == NULL) {
2885         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2886         global_capture_opts.multi_files_on = FALSE;
2887       }
2888       if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2889         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2890         /* XXX - this must be redesigned as the conditions changed */
2891       }
2892     }
2893   }
2894
2895   if (start_capture || list_link_layer_types) {
2896     /* Did the user specify an interface to use? */
2897     status = capture_opts_trim_iface(&global_capture_opts,
2898         ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
2899     if (status != 0) {
2900       exit(status);
2901     }
2902   }
2903
2904   if (list_link_layer_types) {
2905     /* Get the list of link-layer types for the capture devices. */
2906     if_capabilities_t *caps;
2907     guint i;
2908     interface_t device;
2909     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2910
2911       device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2912       if (device.selected) {
2913 #if defined(HAVE_PCAP_CREATE)
2914         caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str);
2915 #else
2916         caps = capture_get_if_capabilities(device.name, FALSE, &err_str);
2917 #endif
2918         if (caps == NULL) {
2919           cmdarg_err("%s", err_str);
2920           g_free(err_str);
2921           exit(2);
2922         }
2923         if (caps->data_link_types == NULL) {
2924           cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
2925           exit(2);
2926         }
2927 #if defined(HAVE_PCAP_CREATE)
2928         capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
2929 #else
2930         capture_opts_print_if_capabilities(caps, device.name, FALSE);
2931 #endif
2932         free_if_capabilities(caps);
2933       }
2934     }
2935     exit(0);
2936   }
2937
2938   capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2939   capture_opts_trim_ring_num_files(&global_capture_opts);
2940 #endif /* HAVE_LIBPCAP */
2941
2942   /* Notify all registered modules that have had any of their preferences
2943      changed either from one of the preferences file or from the command
2944      line that their preferences have changed. */
2945   prefs_apply_all();
2946
2947 #ifdef HAVE_LIBPCAP
2948   if ((global_capture_opts.num_selected == 0) &&
2949       ((prefs.capture_device != NULL) && (*prefs_p->capture_device != '\0'))) {
2950     guint i;
2951     interface_t device;
2952     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2953       device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2954       if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
2955         device.selected = TRUE;
2956         global_capture_opts.num_selected++;
2957         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
2958         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
2959         break;
2960       }
2961     }
2962   }
2963 #endif
2964
2965   /* disabled protocols as per configuration file */
2966   if (gdp_path == NULL && dp_path == NULL) {
2967     set_disabled_protos_list();
2968   }
2969
2970   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2971
2972   /* read in rc file from global and personal configuration paths. */
2973   rc_file = get_datafile_path(RC_FILE);
2974 #if GTK_CHECK_VERSION(3,0,0)
2975   /* XXX resolve later */
2976 #else
2977   gtk_rc_parse(rc_file);
2978   g_free(rc_file);
2979   rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2980   gtk_rc_parse(rc_file);
2981 #endif
2982   g_free(rc_file);
2983
2984   font_init();
2985
2986   macros_init();
2987
2988   stock_icons_init();
2989
2990   /* close the splash screen, as we are going to open the main window now */
2991   splash_destroy(splash_win);
2992
2993   /************************************************************************/
2994   /* Everything is prepared now, preferences and command line was read in */
2995
2996   /* Pop up the main window. */
2997   create_main_window(pl_size, tv_size, bv_size, prefs_p);
2998
2999   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
3000   recent_read_dynamic(&rf_path, &rf_open_errno);
3001   if (rf_path != NULL && rf_open_errno != 0) {
3002     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3003           "Could not open recent file\n\"%s\": %s.",
3004           rf_path, g_strerror(rf_open_errno));
3005   }
3006
3007   color_filters_enable(recent.packet_list_colorize);
3008
3009   /* rearrange all the widgets as we now have all recent settings ready for this */
3010   main_widgets_rearrange();
3011
3012   /* Fill in column titles.  This must be done after the top level window
3013      is displayed.
3014
3015      XXX - is that still true, with fixed-width columns? */
3016
3017   menu_recent_read_finished();
3018 #ifdef HAVE_LIBPCAP
3019   main_auto_scroll_live_changed(auto_scroll_live);
3020 #endif
3021
3022   switch (user_font_apply()) {
3023   case FA_SUCCESS:
3024       break;
3025   case FA_FONT_NOT_RESIZEABLE:
3026       /* "user_font_apply()" popped up an alert box. */
3027       /* turn off zooming - font can't be resized */
3028   case FA_FONT_NOT_AVAILABLE:
3029       /* XXX - did we successfully load the un-zoomed version earlier?
3030       If so, this *probably* means the font is available, but not at
3031       this particular zoom level, but perhaps some other failure
3032       occurred; I'm not sure you can determine which is the case,
3033       however. */
3034       /* turn off zooming - zoom level is unavailable */
3035   default:
3036       /* in any other case than FA_SUCCESS, turn off zooming */
3037       recent.gui_zoom_level = 0;
3038       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
3039   }
3040
3041   dnd_init(top_level);
3042
3043   color_filters_init();
3044   decode_as_init();
3045 #ifdef HAVE_LIBPCAP
3046   capture_filter_init();
3047 #endif
3048
3049   /* the window can be sized only, if it's not already shown, so do it now! */
3050   main_load_window_geometry(top_level);
3051
3052   g_timeout_add(info_update_freq, resolv_update_cb, NULL);
3053
3054   if (dfilter) {
3055     GtkWidget *filter_te;
3056     filter_te = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY)));
3057     gtk_entry_set_text(GTK_ENTRY(filter_te), dfilter);
3058
3059     /* Run the display filter so it goes in effect. */
3060     main_filter_packets(&cfile, dfilter, FALSE);
3061   }
3062
3063   /* If we were given the name of a capture file, read it in now;
3064      we defer it until now, so that, if we can't open it, and pop
3065      up an alert box, the alert box is more likely to come up on
3066      top of the main window - but before the preference-file-error
3067      alert box, so, if we get one of those, it's more likely to come
3068      up on top of us. */
3069   if (cf_name) {
3070     show_main_window(TRUE);
3071     check_and_warn_user_startup(cf_name);
3072     if (rfilter != NULL) {
3073       if (!dfilter_compile(rfilter, &rfcode)) {
3074         bad_dfilter_alert_box(top_level, rfilter);
3075         rfilter_parse_failed = TRUE;
3076       }
3077     }
3078     if (!rfilter_parse_failed) {
3079       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
3080         /* "cf_open()" succeeded, so it closed the previous
3081            capture file, and thus destroyed any previous read filter
3082            attached to "cf". */
3083
3084         cfile.rfcode = rfcode;
3085         /* Open stat windows; we do so after creating the main window,
3086            to avoid GTK warnings, and after successfully opening the
3087            capture file, so we know we have something to compute stats
3088            on, and after registering all dissectors, so that MATE will
3089            have registered its field array and we can have a tap filter
3090            with one of MATE's late-registered fields as part of the
3091            filter. */
3092         start_requested_stats();
3093
3094         /* Read the capture file. */
3095         switch (cf_read(&cfile, FALSE)) {
3096
3097         case CF_READ_OK:
3098         case CF_READ_ERROR:
3099           /* Just because we got an error, that doesn't mean we were unable
3100              to read any of the file; we handle what we could get from the
3101              file. */
3102           /* if the user told us to jump to a specific packet, do it now */
3103           if(go_to_packet != 0) {
3104             /* Jump to the specified frame number, kept for backward
3105                compatibility. */
3106             cf_goto_frame(&cfile, go_to_packet);
3107           } else if (jfilter != NULL) {
3108             /* try to compile given filter */
3109             if (!dfilter_compile(jfilter, &jump_to_filter)) {
3110               bad_dfilter_alert_box(top_level, jfilter);
3111             } else {
3112               /* Filter ok, jump to the first packet matching the filter
3113                  conditions. Default search direction is forward, but if
3114                  option d was given, search backwards */
3115               cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
3116             }
3117           }
3118           break;
3119
3120         case CF_READ_ABORTED:
3121           /* Exit now. */
3122           exit(0);
3123           break;
3124         }
3125
3126         /* If the filename is not the absolute path, prepend the current dir. This happens
3127            when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
3128         if (!g_path_is_absolute(cf_name)) {
3129           char *old_cf_name = cf_name;
3130           char *pwd = g_get_current_dir();
3131           cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
3132           g_free(old_cf_name);
3133           g_free(pwd);
3134         }
3135
3136         /* Save the name of the containing directory specified in the
3137            path name, if any; we can write over cf_name, which is a
3138            good thing, given that "get_dirname()" does write over its
3139            argument. */
3140         s = get_dirname(cf_name);
3141         set_last_open_dir(s);
3142         g_free(cf_name);
3143         cf_name = NULL;
3144       } else {
3145         if (rfcode != NULL)
3146           dfilter_free(rfcode);
3147         cfile.rfcode = NULL;
3148         show_main_window(FALSE);
3149         /* Don't call check_and_warn_user_startup(): we did it above */
3150         main_set_for_capture_in_progress(FALSE);
3151         set_capture_if_dialog_for_capture_in_progress(FALSE);
3152       }
3153     }
3154   } else {
3155 #ifdef HAVE_LIBPCAP
3156     if (start_capture) {
3157       if (global_capture_opts.save_file != NULL) {
3158         /* Save the directory name for future file dialogs. */
3159         /* (get_dirname overwrites filename) */
3160         s = get_dirname(g_strdup(global_capture_opts.save_file));
3161         set_last_open_dir(s);
3162         g_free(s);
3163       }
3164       /* "-k" was specified; start a capture. */
3165       show_main_window(FALSE);
3166       check_and_warn_user_startup(cf_name);
3167
3168       /* If no user interfaces were specified on the command line,
3169          copy the list of selected interfaces to the set of interfaces
3170          to use for this capture. */
3171       if (global_capture_opts.ifaces->len == 0)
3172         collect_ifaces(&global_capture_opts);
3173       if (capture_start(&global_capture_opts)) {
3174         /* The capture started.  Open stat windows; we do so after creating
3175            the main window, to avoid GTK warnings, and after successfully
3176            opening the capture file, so we know we have something to compute
3177            stats on, and after registering all dissectors, so that MATE will
3178            have registered its field array and we can have a tap filter with
3179            one of MATE's late-registered fields as part of the filter. */
3180         start_requested_stats();
3181       }
3182     } else {
3183       show_main_window(FALSE);
3184       check_and_warn_user_startup(cf_name);
3185       main_set_for_capture_in_progress(FALSE);
3186       set_capture_if_dialog_for_capture_in_progress(FALSE);
3187     }
3188
3189     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
3190     if (!start_capture && !global_capture_opts.default_options.cfilter) {
3191       global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
3192     }
3193 #else /* HAVE_LIBPCAP */
3194     show_main_window(FALSE);
3195     check_and_warn_user_startup(cf_name);
3196     main_set_for_capture_in_progress(FALSE);
3197     set_capture_if_dialog_for_capture_in_progress(FALSE);
3198 #endif /* HAVE_LIBPCAP */
3199   }
3200
3201   /* register our pid if we are being run from a U3 device */
3202   u3_register_pid();
3203
3204   profile_store_persconffiles (FALSE);
3205
3206 #ifdef HAVE_GTKOSXAPPLICATION
3207   theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
3208   gtkosx_application_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3209   gtkosx_application_ready(theApp);
3210 #endif
3211
3212   g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3213
3214 #ifdef HAVE_LIBPCAP
3215   gtk_iface_mon_start();
3216 #endif
3217
3218   /* we'll enter the GTK loop now and hand the control over to GTK ... */
3219   gtk_main();
3220   /* ... back from GTK, we're going down now! */
3221
3222 #ifdef HAVE_LIBPCAP
3223   gtk_iface_mon_stop();
3224 #endif
3225
3226   /* deregister our pid */
3227   u3_deregister_pid();
3228
3229   epan_cleanup();
3230
3231   AirPDcapDestroyContext(&airpdcap_ctx);
3232
3233 #ifdef _WIN32
3234   /* hide the (unresponsive) main window, while asking the user to close the console window */
3235   gtk_widget_hide(top_level);
3236
3237 #ifdef HAVE_GTKOSXAPPLICATION
3238   g_object_unref(theApp);
3239 #endif
3240
3241   /* Shutdown windows sockets */
3242   WSACleanup();
3243
3244   /* For some unknown reason, the "atexit()" call in "create_console()"
3245      doesn't arrange that "destroy_console()" be called when we exit,
3246      so we call it here if a console was created. */
3247   destroy_console();
3248 #endif
3249
3250   exit(0);
3251 }
3252
3253 #ifdef _WIN32
3254
3255 /* We build this as a GUI subsystem application on Win32, so
3256    "WinMain()", not "main()", gets called.
3257
3258    Hack shamelessly stolen from the Win32 port of the GIMP. */
3259 #ifdef __GNUC__
3260 #define _stdcall  __attribute__((stdcall))
3261 #endif
3262
3263 int _stdcall
3264 WinMain (struct HINSTANCE__ *hInstance,
3265          struct HINSTANCE__ *hPrevInstance,
3266          char               *lpszCmdLine,
3267          int                 nCmdShow)
3268 {
3269   INITCOMMONCONTROLSEX comm_ctrl;
3270
3271   /*
3272    * Initialize our DLL search path. MUST be called before LoadLibrary
3273    * or g_module_open.
3274    */
3275   ws_init_dll_search_path();
3276
3277   /* Initialize our controls. Required for native Windows file dialogs. */
3278   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3279   comm_ctrl.dwSize = sizeof(comm_ctrl);
3280   /* Includes the animate, header, hot key, list view, progress bar,
3281    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3282    * up-down controls
3283    */
3284   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3285   InitCommonControlsEx(&comm_ctrl);
3286
3287   /* RichEd20.DLL is needed for filter entries. */
3288   ws_load_library("riched20.dll");
3289
3290   set_has_console(FALSE);
3291   set_console_wait(FALSE);
3292   return main (__argc, __argv);
3293 }
3294
3295 #endif /* _WIN32 */
3296
3297
3298 static void
3299 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3300                     const char *message, gpointer user_data _U_)
3301 {
3302   time_t curr;
3303   struct tm *today;
3304   const char *level;
3305
3306
3307   /* ignore log message, if log_level isn't interesting based
3308      upon the console log preferences.
3309      If the preferences haven't been loaded loaded yet, display the
3310      message anyway.
3311
3312      The default console_log_level preference value is such that only
3313        ERROR, CRITICAL and WARNING level messages are processed;
3314        MESSAGE, INFO and DEBUG level messages are ignored.  */
3315   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3316      prefs.console_log_level != 0) {
3317     return;
3318   }
3319
3320 #ifdef _WIN32
3321   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3322     /* the user wants a console or the application will terminate immediately */
3323     create_console();
3324   }
3325   if (get_has_console()) {
3326     /* For some unknown reason, the above doesn't appear to actually cause
3327        anything to be sent to the standard output, so we'll just splat the
3328        message out directly, just to make sure it gets out. */
3329 #endif
3330     switch(log_level & G_LOG_LEVEL_MASK) {
3331     case G_LOG_LEVEL_ERROR:
3332         level = "Err ";
3333         break;
3334     case G_LOG_LEVEL_CRITICAL:
3335         level = "Crit";
3336         break;
3337     case G_LOG_LEVEL_WARNING:
3338         level = "Warn";
3339         break;
3340     case G_LOG_LEVEL_MESSAGE:
3341         level = "Msg ";
3342         break;
3343     case G_LOG_LEVEL_INFO:
3344         level = "Info";
3345         break;
3346     case G_LOG_LEVEL_DEBUG:
3347         level = "Dbg ";
3348         break;
3349     default:
3350         fprintf(stderr, "unknown log_level %u\n", log_level);
3351         level = NULL;
3352         g_assert_not_reached();
3353     }
3354
3355     /* create a "timestamp" */
3356     time(&curr);
3357     today = localtime(&curr);
3358
3359     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3360             today->tm_hour, today->tm_min, today->tm_sec,
3361             log_domain != NULL ? log_domain : "",
3362             level, message);
3363 #ifdef _WIN32
3364     if(log_level & G_LOG_LEVEL_ERROR) {
3365         /* wait for a key press before the following error handler will terminate the program
3366            this way the user at least can read the error message */
3367         printf("\n\nPress any key to exit\n");
3368         _getch();
3369     }
3370   } else {
3371     /* XXX - on UN*X, should we just use g_log_default_handler()?
3372        We want the error messages to go to the standard output;
3373        on Mac OS X, that will cause them to show up in various
3374        per-user logs accessible through Console (details depend
3375        on whether you're running 10.0 through 10.4 or running
3376        10.5 and later), and, on other UN*X desktop environments,
3377        if they don't show up in some form of console log, that's
3378        a deficiency in that desktop environment.  (Too bad
3379        Windows doesn't set the standard output and error for
3380        GUI apps to something that shows up in such a log.) */
3381     g_log_default_handler(log_domain, log_level, message, user_data);
3382   }
3383 #endif
3384 }
3385
3386
3387 /*
3388  * Helper for main_widgets_rearrange()
3389  */
3390 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3391     gtk_container_remove(GTK_CONTAINER(data), widget);
3392 }
3393
3394 static GtkWidget *main_widget_layout(gint layout_content)
3395 {
3396     switch(layout_content) {
3397     case(layout_pane_content_none):
3398         return NULL;
3399     case(layout_pane_content_plist):
3400         return pkt_scrollw;
3401     case(layout_pane_content_pdetails):
3402         return tv_scrollw;
3403     case(layout_pane_content_pbytes):
3404         return byte_nb_ptr_gbl;
3405     default:
3406         g_assert_not_reached();
3407         return NULL;
3408     }
3409 }
3410
3411
3412 /*
3413  * Rearrange the main window widgets
3414  */
3415 void main_widgets_rearrange(void) {
3416     GtkWidget *first_pane_widget1, *first_pane_widget2;
3417     GtkWidget *second_pane_widget1, *second_pane_widget2;
3418     gboolean split_top_left = FALSE;
3419
3420     /* be a bit faster */
3421     gtk_widget_hide(main_vbox);
3422
3423     /* be sure we don't lose a widget while rearranging */
3424     g_object_ref(G_OBJECT(menubar));
3425     g_object_ref(G_OBJECT(main_tb));
3426     g_object_ref(G_OBJECT(filter_tb));
3427     g_object_ref(G_OBJECT(wireless_tb));
3428     g_object_ref(G_OBJECT(pkt_scrollw));
3429     g_object_ref(G_OBJECT(tv_scrollw));
3430     g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3431     g_object_ref(G_OBJECT(statusbar));
3432     g_object_ref(G_OBJECT(main_pane_v1));
3433     g_object_ref(G_OBJECT(main_pane_v2));
3434     g_object_ref(G_OBJECT(main_pane_h1));
3435     g_object_ref(G_OBJECT(main_pane_h2));
3436     g_object_ref(G_OBJECT(welcome_pane));
3437
3438     /* empty all containers participating */
3439     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3440     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3441     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3442     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3443     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3444
3445     statusbar_widgets_emptying(statusbar);
3446
3447     /* add the menubar always at the top */
3448     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3449
3450     /* main toolbar */
3451     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3452
3453     /* filter toolbar in toolbar area */
3454     if (!prefs.filter_toolbar_show_in_statusbar) {
3455         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3456     }
3457
3458     /* airpcap toolbar */
3459     gtk_box_pack_start(GTK_BOX(main_vbox), wireless_tb, FALSE, TRUE, 1);
3460
3461     /* fill the main layout panes */
3462     switch(prefs.gui_layout_type) {
3463     case(layout_type_5):
3464         main_first_pane  = main_pane_v1;
3465         main_second_pane = main_pane_v2;
3466         split_top_left = FALSE;
3467         break;
3468     case(layout_type_2):
3469         main_first_pane  = main_pane_v1;
3470         main_second_pane = main_pane_h1;
3471         split_top_left = FALSE;
3472         break;
3473     case(layout_type_1):
3474         main_first_pane  = main_pane_v1;
3475         main_second_pane = main_pane_h1;
3476         split_top_left = TRUE;
3477         break;
3478     case(layout_type_4):
3479         main_first_pane  = main_pane_h1;
3480         main_second_pane = main_pane_v1;
3481         split_top_left = FALSE;
3482         break;
3483     case(layout_type_3):
3484         main_first_pane  = main_pane_h1;
3485         main_second_pane = main_pane_v1;
3486         split_top_left = TRUE;
3487         break;
3488     case(layout_type_6):
3489         main_first_pane  = main_pane_h1;
3490         main_second_pane = main_pane_h2;
3491         split_top_left = FALSE;
3492         break;
3493     default:
3494         main_first_pane = NULL;
3495         main_second_pane = NULL;
3496         g_assert_not_reached();
3497     }
3498     if (split_top_left) {
3499         first_pane_widget1 = main_second_pane;
3500         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3501         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3502         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3503     } else {
3504         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3505         first_pane_widget2 = main_second_pane;
3506         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3507         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3508     }
3509     if (first_pane_widget1 != NULL)
3510         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3511     if (first_pane_widget2 != NULL)
3512         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3513     if (second_pane_widget1 != NULL)
3514         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3515     if (second_pane_widget2 != NULL)
3516         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3517
3518     gtk_box_pack_start(GTK_BOX(main_vbox), main_first_pane, TRUE, TRUE, 0);
3519
3520     /* welcome pane */
3521     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3522
3523     /* statusbar */
3524     gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3525
3526     /* filter toolbar in statusbar hbox */
3527     if (prefs.filter_toolbar_show_in_statusbar) {
3528         gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3529     }
3530
3531     /* statusbar widgets */
3532     statusbar_widgets_pack(statusbar);
3533
3534     /* hide widgets on users recent settings */
3535     main_widgets_show_or_hide();
3536
3537     gtk_widget_show(main_vbox);
3538 }
3539
3540 static void
3541 is_widget_visible(GtkWidget *widget, gpointer data)
3542 {
3543     gboolean *is_visible = data;
3544
3545     if (!*is_visible) {
3546         if (gtk_widget_get_visible(widget))
3547             *is_visible = TRUE;
3548     }
3549 }
3550
3551
3552 void
3553 main_widgets_show_or_hide(void)
3554 {
3555     gboolean main_second_pane_show;
3556
3557     if (recent.main_toolbar_show) {
3558         gtk_widget_show(main_tb);
3559     } else {
3560         gtk_widget_hide(main_tb);
3561     }
3562
3563     statusbar_widgets_show_or_hide(statusbar);
3564
3565     if (recent.filter_toolbar_show) {
3566         gtk_widget_show(filter_tb);
3567     } else {
3568         gtk_widget_hide(filter_tb);
3569     }
3570
3571     if (recent.wireless_toolbar_show) {
3572         gtk_widget_show(wireless_tb);
3573     } else {
3574         gtk_widget_hide(wireless_tb);
3575     }
3576
3577     if (recent.packet_list_show && have_capture_file) {
3578         gtk_widget_show(pkt_scrollw);
3579     } else {
3580         gtk_widget_hide(pkt_scrollw);
3581     }
3582
3583     if (recent.tree_view_show && have_capture_file) {
3584         gtk_widget_show(tv_scrollw);
3585     } else {
3586         gtk_widget_hide(tv_scrollw);
3587     }
3588
3589     if (recent.byte_view_show && have_capture_file) {
3590         gtk_widget_show(byte_nb_ptr_gbl);
3591     } else {
3592         gtk_widget_hide(byte_nb_ptr_gbl);
3593     }
3594
3595     if (have_capture_file) {
3596         gtk_widget_show(main_first_pane);
3597     } else {
3598         gtk_widget_hide(main_first_pane);
3599     }
3600
3601     /*
3602      * Is anything in "main_second_pane" visible?
3603      * If so, show it, otherwise hide it.
3604      */
3605     main_second_pane_show = FALSE;
3606     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3607                           &main_second_pane_show);
3608     if (main_second_pane_show) {
3609         gtk_widget_show(main_second_pane);
3610     } else {
3611         gtk_widget_hide(main_second_pane);
3612     }
3613
3614     if (!have_capture_file) {
3615         if(welcome_pane) {
3616             gtk_widget_show(welcome_pane);
3617         }
3618     } else {
3619         gtk_widget_hide(welcome_pane);
3620     }
3621 }
3622
3623
3624 /* called, when the window state changes (minimized, maximized, ...) */
3625 static gboolean
3626 window_state_event_cb (GtkWidget *widget _U_,
3627                        GdkEvent *event,
3628                        gpointer  data _U_)
3629 {
3630     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3631
3632     if( (event->type) == (GDK_WINDOW_STATE)) {
3633         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3634             /* we might have dialogs popped up while we where iconified,
3635                show em now */
3636             display_queued_messages();
3637         }
3638     }
3639     return FALSE;
3640 }
3641
3642
3643
3644 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3645 static gboolean
3646 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3647 {
3648     if (event->keyval == GDK_F8) {
3649         packet_list_next();
3650         return TRUE;
3651     } else if (event->keyval == GDK_F7) {
3652         packet_list_prev();
3653         return TRUE;
3654     } else if (event->state & NO_SHIFT_MOD_MASK) {
3655         return FALSE; /* Skip control, alt, and other modifiers */
3656     /*
3657      * A comment in gdkkeysyms.h says that it's autogenerated from
3658      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
3659      * don't explicitly say so, isprint() should work as expected
3660      * for values < 127.
3661      */
3662     } else if (isascii(event->keyval) && isprint(event->keyval)) {
3663         /* Forward the keypress on to the display filter entry */
3664         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3665             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3666             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3667         }
3668         return FALSE;
3669     }
3670     return FALSE;
3671 }
3672
3673 static void
3674 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p
3675 #if !defined(HAVE_IGE_MAC_INTEGRATION) && !defined (HAVE_GTKOSXAPPLICATION)
3676                     _U_
3677 #endif
3678                     )
3679 {
3680     GtkAccelGroup *accel;
3681
3682     /* Main window */
3683     top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3684     main_set_window_name("The Wireshark Network Analyzer");
3685
3686     gtk_widget_set_name(top_level, "main window");
3687     g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3688                    NULL);
3689     g_signal_connect(G_OBJECT(top_level), "window_state_event",
3690                          G_CALLBACK(window_state_event_cb), NULL);
3691     g_signal_connect(G_OBJECT(top_level), "key-press-event",
3692                          G_CALLBACK(top_level_key_pressed_cb), NULL );
3693
3694     /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3695     main_vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 1, FALSE);
3696
3697         gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3698     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3699     gtk_widget_show(main_vbox);
3700
3701     /* Menu bar */
3702     menubar = main_menu_new(&accel);
3703
3704 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3705     /* Mac OS X native menus are created and displayed by main_menu_new() */
3706     if(!prefs_p->gui_macosx_style) {
3707 #endif
3708     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3709     gtk_widget_show(menubar);
3710 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3711     } else {
3712     gtk_widget_hide(menubar);
3713     }
3714 #endif
3715
3716     /* Main Toolbar */
3717     main_tb = toolbar_new();
3718     gtk_widget_show (main_tb);
3719
3720     /* Filter toolbar */
3721     filter_tb = filter_toolbar_new();
3722
3723     /* Packet list */
3724     pkt_scrollw = packet_list_create();
3725     gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3726     gtk_widget_show_all(pkt_scrollw);
3727
3728     /* Tree view */
3729     tv_scrollw = proto_tree_view_new(&tree_view_gbl);
3730     gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3731     gtk_widget_show(tv_scrollw);
3732
3733     g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3734                    "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3735     g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3736                    g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3737     gtk_widget_show(tree_view_gbl);
3738
3739     /* Byte view. */
3740     byte_nb_ptr_gbl = byte_view_new();
3741     gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3742     gtk_widget_show(byte_nb_ptr_gbl);
3743
3744     g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3745                    g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3746
3747     /* Panes for the packet list, tree, and byte view */
3748     main_pane_v1 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3749     gtk_widget_show(main_pane_v1);
3750     main_pane_v2 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3751     gtk_widget_show(main_pane_v2);
3752     main_pane_h1 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3753     gtk_widget_show(main_pane_h1);
3754     main_pane_h2 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3755     gtk_widget_show(main_pane_h2);
3756 #ifdef HAVE_AIRPCAP
3757     wireless_tb = airpcap_toolbar_new();
3758 #else
3759     wireless_tb = ws80211_toolbar_new();
3760 #endif
3761     gtk_widget_show(wireless_tb);
3762
3763     /* status bar */
3764     statusbar = statusbar_new();
3765     gtk_widget_show(statusbar);
3766
3767     /* Pane for the welcome screen */
3768     welcome_pane = welcome_new();
3769     gtk_widget_show(welcome_pane);
3770 }
3771
3772 static void
3773 show_main_window(gboolean doing_work)
3774 {
3775   main_set_for_capture_file(doing_work);
3776
3777   /*** we have finished all init things, show the main window ***/
3778   gtk_widget_show(top_level);
3779
3780   /* the window can be maximized only, if it's visible, so do it after show! */
3781   main_load_window_geometry(top_level);
3782
3783   /* process all pending GUI events before continue */
3784   while (gtk_events_pending()) gtk_main_iteration();
3785
3786   /* Pop up any queued-up alert boxes. */
3787   display_queued_messages();
3788
3789   /* Move the main window to the front, in case it isn't already there */
3790   gdk_window_raise(gtk_widget_get_window(top_level));
3791
3792 #ifdef HAVE_AIRPCAP
3793   airpcap_toolbar_show(wireless_tb);
3794 #endif /* HAVE_AIRPCAP */
3795 }
3796
3797 static void copy_global_profile (const gchar *profile_name)
3798 {
3799     char  *pf_dir_path, *pf_dir_path2, *pf_filename;
3800
3801     if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
3802         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3803             "Can't create directory\n\"%s\":\n%s.",
3804             pf_dir_path, g_strerror(errno));
3805
3806         g_free(pf_dir_path);
3807     }
3808
3809     if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
3810             &pf_dir_path, &pf_dir_path2) == -1) {
3811         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3812             "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
3813             pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
3814
3815         g_free(pf_filename);
3816         g_free(pf_dir_path);
3817         g_free(pf_dir_path2);
3818     }
3819 }
3820
3821 /* Change configuration profile */
3822 void change_configuration_profile (const gchar *profile_name)
3823 {
3824     char  *gdp_path, *dp_path;
3825     char  *rf_path;
3826     int    rf_open_errno;
3827
3828     /* First check if profile exists */
3829     if (!profile_exists(profile_name, FALSE)) {
3830         if (profile_exists(profile_name, TRUE)) {
3831            /* Copy from global profile */
3832             copy_global_profile (profile_name);
3833         } else {
3834             /* No personal and no global profile exists */
3835             return;
3836         }
3837     }
3838
3839     /* Then check if changing to another profile */
3840     if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
3841         return;
3842     }
3843
3844     /* Get the current geometry, before writing it to disk */
3845     main_save_window_geometry(top_level);
3846
3847     if (profile_exists(get_profile_name(), FALSE)) {
3848         /* Write recent file for profile we are leaving, if it still exists */
3849         write_profile_recent();
3850     }
3851
3852     /* Set profile name and update the status bar */
3853     set_profile_name (profile_name);
3854     profile_bar_update ();
3855     filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY);
3856
3857     /* Reset current preferences and apply the new */
3858     prefs_reset();
3859     menu_prefs_reset();
3860
3861     (void) read_configuration_files (&gdp_path, &dp_path);
3862
3863     recent_read_profile_static(&rf_path, &rf_open_errno);
3864     if (rf_path != NULL && rf_open_errno != 0) {
3865         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3866             "Could not open common recent file\n\"%s\": %s.",
3867             rf_path, g_strerror(rf_open_errno));
3868     }
3869     if (recent.gui_fileopen_remembered_dir &&
3870         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3871         set_last_open_dir(recent.gui_fileopen_remembered_dir);
3872     }
3873     timestamp_set_type (recent.gui_time_format);
3874     timestamp_set_seconds_type (recent.gui_seconds_format);
3875     color_filters_enable(recent.packet_list_colorize);
3876
3877     prefs_to_capture_opts();
3878     prefs_apply_all();
3879     macros_post_update();
3880
3881     /* Update window view and redraw the toolbar */
3882     main_titlebar_update();
3883     filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
3884     toolbar_redraw_all();
3885
3886     /* Enable all protocols and disable from the disabled list */
3887     proto_enable_all();
3888     if (gdp_path == NULL && dp_path == NULL) {
3889         set_disabled_protos_list();
3890     }
3891
3892     /* Reload color filters */
3893     color_filters_reload();
3894
3895     /* Reload list of interfaces on welcome page */
3896     welcome_if_panel_reload();
3897
3898     /* Recreate the packet list according to new preferences */
3899     packet_list_recreate ();
3900     cfile.columns_changed = FALSE; /* Reset value */
3901     user_font_apply();
3902
3903     /* Update menus with new recent values */
3904     menu_recent_read_finished();
3905
3906     /* Reload pane geometry, must be done after recreating the list */
3907     main_pane_load_window_geometry();
3908 }
3909
3910 /** redissect packets and update UI */
3911 void redissect_packets(void)
3912 {
3913     cf_redissect_packets(&cfile);
3914     status_expert_update();
3915 }