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