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