Move capture_globals.h from ui/gtk/ to ui/. Show interface activity
[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.cinfo.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
1188   /*fprintf(output, "\n");*/
1189   fprintf(output, "Input file:\n");
1190   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
1191
1192   fprintf(output, "\n");
1193   fprintf(output, "Processing:\n");
1194   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
1195   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
1196   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
1197
1198   fprintf(output, "\n");
1199   fprintf(output, "User interface:\n");
1200   fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
1201   fprintf(output, "  -d <display filter>      start with the given display filter\n");
1202   fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
1203   fprintf(output, "  -J <jump filter>         jump to the first packet matching the (display)\n");
1204   fprintf(output, "                           filter\n");
1205   fprintf(output, "  -j                       search backwards for a matching packet after \"-J\"\n");
1206   fprintf(output, "  -m <font>                set the font name used for most text\n");
1207   fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
1208   fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
1209   fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
1210   fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
1211
1212   fprintf(output, "\n");
1213   fprintf(output, "Output:\n");
1214   fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
1215
1216   fprintf(output, "\n");
1217   fprintf(output, "Miscellaneous:\n");
1218   fprintf(output, "  -h                       display this help and exit\n");
1219   fprintf(output, "  -v                       display version info and exit\n");
1220   fprintf(output, "  -P <key>:<path>          persconf:path - personal configuration files\n");
1221   fprintf(output, "                           persdata:path - personal data files\n");
1222   fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
1223   fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
1224 #ifndef _WIN32
1225   fprintf(output, "  --display=DISPLAY        X display to use\n");
1226 #endif
1227
1228 #ifdef _WIN32
1229   destroy_console();
1230 #endif
1231 }
1232
1233 static void
1234 show_version(void)
1235 {
1236 #ifdef _WIN32
1237   create_console();
1238 #endif
1239
1240   printf(PACKAGE " " VERSION "%s\n"
1241          "\n"
1242          "%s"
1243          "\n"
1244          "%s"
1245          "\n"
1246          "%s",
1247       wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1248       runtime_info_str->str);
1249
1250 #ifdef _WIN32
1251   destroy_console();
1252 #endif
1253 }
1254
1255 /*
1256  * Print to the standard error.  On Windows, create a console for the
1257  * standard error to show up on, if necessary.
1258  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1259  * terminal isn't the standard error?
1260  */
1261 void
1262 vfprintf_stderr(const char *fmt, va_list ap)
1263 {
1264 #ifdef _WIN32
1265   create_console();
1266 #endif
1267   vfprintf(stderr, fmt, ap);
1268 }
1269
1270 void
1271 fprintf_stderr(const char *fmt, ...)
1272 {
1273   va_list ap;
1274
1275   va_start(ap, fmt);
1276   vfprintf_stderr(fmt, ap);
1277   va_end(ap);
1278 }
1279
1280 /*
1281  * Report an error in command-line arguments.
1282  * Creates a console on Windows.
1283  */
1284 void
1285 cmdarg_err(const char *fmt, ...)
1286 {
1287   va_list ap;
1288
1289   fprintf_stderr("wireshark: ");
1290   va_start(ap, fmt);
1291   vfprintf_stderr(fmt, ap);
1292   va_end(ap);
1293   fprintf_stderr("\n");
1294 }
1295
1296 /*
1297  * Report additional information for an error in command-line arguments.
1298  * Creates a console on Windows.
1299  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1300  * terminal isn't the standard error?
1301  */
1302 void
1303 cmdarg_err_cont(const char *fmt, ...)
1304 {
1305   va_list ap;
1306
1307   va_start(ap, fmt);
1308   vfprintf_stderr(fmt, ap);
1309   fprintf_stderr("\n");
1310   va_end(ap);
1311 }
1312
1313 /*
1314    Once every 3 seconds we get a callback here which we use to update
1315    the tap extensions.
1316  */
1317 static gboolean
1318 tap_update_cb(gpointer data _U_)
1319 {
1320     draw_tap_listeners(FALSE);
1321     return TRUE;
1322 }
1323
1324 /* Restart the tap update display timer with new configured interval */
1325 void reset_tap_update_timer(void)
1326 {
1327     g_source_remove(tap_update_timer_id);
1328     tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1329 }
1330
1331 void
1332 protect_thread_critical_region(void)
1333 {
1334     /* Threading support for TAP:s removed
1335      * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1336      * See the commit for removed code:
1337      * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
1338      */
1339 }
1340 void
1341 unprotect_thread_critical_region(void)
1342 {
1343     /* Threading support for TAP:s removed
1344      * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1345      */
1346
1347 }
1348
1349 /*
1350  * Periodically process outstanding hostname lookups. If we have new items,
1351  * redraw the packet list and tree view.
1352  */
1353
1354 static gboolean
1355 resolv_update_cb(gpointer data _U_)
1356 {
1357   /* Anything new show up? */
1358   if (host_name_lookup_process(NULL)) {
1359     if (gtk_widget_get_window(pkt_scrollw))
1360       gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
1361     if (gtk_widget_get_window(tv_scrollw))
1362       gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
1363   }
1364
1365   /* Always check. Even if we don't do async lookups we could still get
1366      passive updates, e.g. from DNS packets. */
1367   return TRUE;
1368 }
1369
1370
1371 /* Set main_window_name and it's icon title to the capture filename */
1372 static void
1373 set_display_filename(capture_file *cf)
1374 {
1375   gchar *display_name;
1376   gchar *window_name;
1377
1378   if (cf->filename) {
1379     display_name = cf_get_display_name(cf);
1380     window_name = g_strdup_printf("%s%s", cf->unsaved_changes ? "*" : "",
1381                                   display_name);
1382     g_free(display_name);
1383     main_set_window_name(window_name);
1384     g_free(window_name);
1385   } else {
1386     main_set_window_name("The Wireshark Network Analyzer");
1387   }
1388 }
1389
1390 /* Update various parts of the main window for a capture file "unsaved
1391    changes" change - update the title to reflect whether there are
1392    unsaved changes or not, and update the menus and toolbar to
1393    enable or disable the "Save" operation. */
1394 void
1395 main_update_for_unsaved_changes(capture_file *cf)
1396 {
1397   set_display_filename(cf);
1398   set_menus_for_capture_file(cf);
1399   set_toolbar_for_capture_file(cf);
1400 }
1401
1402 #ifdef HAVE_LIBPCAP
1403 void
1404 main_auto_scroll_live_changed(gboolean auto_scroll_live_in)
1405 {
1406   /* Update menubar and toolbar */
1407   menu_auto_scroll_live_changed(auto_scroll_live_in);
1408   toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1409
1410   /* change auto scroll state */
1411   auto_scroll_live  = auto_scroll_live_in;
1412 }
1413 #endif
1414
1415 void
1416 main_colorize_changed(gboolean packet_list_colorize)
1417 {
1418   /* Update menubar and toolbar */
1419   menu_colorize_changed(packet_list_colorize);
1420   toolbar_colorize_changed(packet_list_colorize);
1421
1422   /* change colorization */
1423   if(packet_list_colorize != recent.packet_list_colorize) {
1424       recent.packet_list_colorize = packet_list_colorize;
1425       color_filters_enable(packet_list_colorize);
1426       new_packet_list_colorize_packets();
1427   }
1428 }
1429
1430 static GtkWidget           *close_dlg = NULL;
1431
1432 static void
1433 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1434 {
1435     recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1436 }
1437
1438 #ifdef _WIN32
1439 static void
1440 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1441 {
1442     recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1443 }
1444 #endif
1445
1446 static void
1447 main_cf_cb_file_closing(capture_file *cf)
1448 {
1449     /* if we have more than 10000 packets, show a splash screen while closing */
1450     /* XXX - don't know a better way to decide whether to show or not,
1451      * as most of the time is spend in various calls that destroy various
1452      * data structures, so it wouldn't be easy to use a progress bar,
1453      * rather than, say, a progress spinner, here! */
1454     if(cf->count > 10000) {
1455         close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1456                                   "%sClosing file!%s\n\nPlease wait ...",
1457                                   simple_dialog_primary_start(),
1458                                   simple_dialog_primary_end());
1459         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1460     }
1461
1462     /* Destroy all windows that refer to the
1463        capture file we're closing. */
1464     destroy_packet_wins();
1465
1466     /* Restore the standard title bar message. */
1467     main_set_window_name("The Wireshark Network Analyzer");
1468
1469     /* Disable all menu items that make sense only if you have a capture. */
1470     set_menus_for_capture_file(NULL);
1471     set_toolbar_for_capture_file(NULL);
1472     main_set_for_captured_packets(FALSE);
1473     set_menus_for_selected_packet(cf);
1474     main_set_for_capture_in_progress(FALSE);
1475     set_capture_if_dialog_for_capture_in_progress(FALSE);
1476     set_menus_for_selected_tree_row(cf);
1477
1478     /* Set up main window for no capture file. */
1479     main_set_for_capture_file(FALSE);
1480
1481     main_window_update();
1482 }
1483
1484 static void
1485 main_cf_cb_file_closed(capture_file *cf _U_)
1486 {
1487   if(close_dlg != NULL) {
1488     splash_destroy(close_dlg);
1489     close_dlg = NULL;
1490   }
1491 }
1492
1493
1494 static void
1495 main_cf_cb_file_read_started(capture_file *cf _U_)
1496 {
1497   tap_param_dlg_update();
1498
1499   /* Set up main window for a capture file. */
1500   main_set_for_capture_file(TRUE);
1501 }
1502
1503 static void
1504 main_cf_cb_file_read_finished(capture_file *cf)
1505 {
1506     gchar *dir_path;
1507
1508     if (!cf->is_tempfile && cf->filename) {
1509         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1510         add_menu_recent_capture_file(cf->filename);
1511
1512         /* Remember folder for next Open dialog and save it in recent */
1513         dir_path = get_dirname(g_strdup(cf->filename));
1514         set_last_open_dir(dir_path);
1515         g_free(dir_path);
1516     }
1517
1518     /* Update the appropriate parts of the main window. */
1519     main_update_for_unsaved_changes(cf);
1520
1521     /* Enable menu items that make sense if you have some captured packets. */
1522     main_set_for_captured_packets(TRUE);
1523 }
1524
1525 static void
1526 main_cf_cb_file_rescan_finished(capture_file *cf)
1527 {
1528     gchar *dir_path;
1529
1530     if (!cf->is_tempfile && cf->filename) {
1531         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1532         add_menu_recent_capture_file(cf->filename);
1533
1534         /* Remember folder for next Open dialog and save it in recent */
1535         dir_path = get_dirname(g_strdup(cf->filename));
1536         set_last_open_dir(dir_path);
1537         g_free(dir_path);
1538     }
1539
1540     /* Update the appropriate parts of the main window. */
1541     main_update_for_unsaved_changes(cf);
1542 }
1543
1544 #ifdef HAVE_LIBPCAP
1545 static GList *icon_list_create(
1546     const char **icon16_xpm,
1547     const char **icon32_xpm,
1548     const char **icon48_xpm,
1549     const char **icon64_xpm)
1550 {
1551   GList *icon_list = NULL;
1552   GdkPixbuf * pixbuf16;
1553   GdkPixbuf * pixbuf32;
1554   GdkPixbuf * pixbuf48;
1555   GdkPixbuf * pixbuf64;
1556
1557
1558   if(icon16_xpm != NULL) {
1559       pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1560       g_assert(pixbuf16);
1561       icon_list = g_list_append(icon_list, pixbuf16);
1562   }
1563
1564   if(icon32_xpm != NULL) {
1565       pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1566       g_assert(pixbuf32);
1567       icon_list = g_list_append(icon_list, pixbuf32);
1568   }
1569
1570   if(icon48_xpm != NULL) {
1571       pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1572       g_assert(pixbuf48);
1573       icon_list = g_list_append(icon_list, pixbuf48);
1574   }
1575
1576   if(icon64_xpm != NULL) {
1577       pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1578       g_assert(pixbuf64);
1579       icon_list = g_list_append(icon_list, pixbuf64);
1580   }
1581
1582   return icon_list;
1583 }
1584
1585 static void
1586 main_capture_set_main_window_title(capture_options *capture_opts)
1587 {
1588     GString *title = g_string_new("");
1589
1590     g_string_append(title, "Capturing ");
1591     g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1592     main_set_window_name(title->str);
1593     g_string_free(title, TRUE);
1594 }
1595
1596 static void
1597 main_capture_cb_capture_prepared(capture_options *capture_opts)
1598 {
1599     static GList *icon_list = NULL;
1600
1601     main_capture_set_main_window_title(capture_opts);
1602
1603     if(icon_list == NULL) {
1604         icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1605     }
1606     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1607
1608     /* Disable menu items that make no sense if you're currently running
1609        a capture. */
1610     main_set_for_capture_in_progress(TRUE);
1611     set_capture_if_dialog_for_capture_in_progress(TRUE);
1612
1613     /* Don't set up main window for a capture file. */
1614     main_set_for_capture_file(FALSE);
1615 }
1616
1617 static void
1618 main_capture_cb_capture_update_started(capture_options *capture_opts)
1619 {
1620     /* We've done this in "prepared" above, but it will be cleared while
1621        switching to the next multiple file. */
1622     main_capture_set_main_window_title(capture_opts);
1623
1624     main_set_for_capture_in_progress(TRUE);
1625     set_capture_if_dialog_for_capture_in_progress(TRUE);
1626
1627     /* Enable menu items that make sense if you have some captured
1628        packets (yes, I know, we don't have any *yet*). */
1629     main_set_for_captured_packets(TRUE);
1630
1631     /* Set up main window for a capture file. */
1632     main_set_for_capture_file(TRUE);
1633 }
1634
1635 static void
1636 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1637 {
1638     capture_file *cf = capture_opts->cf;
1639     static GList *icon_list = NULL;
1640
1641     /* The capture isn't stopping any more - it's stopped. */
1642     capture_stopping = FALSE;
1643
1644     if (!cf->is_tempfile && cf->filename) {
1645         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1646         add_menu_recent_capture_file(cf->filename);
1647     }
1648
1649     /* Update the main window as appropriate */
1650     main_update_for_unsaved_changes(cf);
1651
1652     /* Enable menu items that make sense if you're not currently running
1653      a capture. */
1654     main_set_for_capture_in_progress(FALSE);
1655     set_capture_if_dialog_for_capture_in_progress(FALSE);
1656
1657     /* Set up main window for a capture file. */
1658     main_set_for_capture_file(TRUE);
1659
1660     if(icon_list == NULL) {
1661         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1662     }
1663     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1664
1665     if(global_capture_opts.quit_after_cap) {
1666         /* command line asked us to quit after the capture */
1667         /* don't pop up a dialog to ask for unsaved files etc. */
1668         main_do_quit();
1669     }
1670 }
1671
1672 static void
1673 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1674 {
1675     /* Don't set up main window for a capture file. */
1676     main_set_for_capture_file(FALSE);
1677 }
1678
1679 static void
1680 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1681 {
1682 #if 0
1683     capture_file *cf = capture_opts->cf;
1684 #endif
1685     static GList *icon_list = NULL;
1686
1687     /* The capture isn't stopping any more - it's stopped. */
1688     capture_stopping = FALSE;
1689
1690     /*set_display_filename(cf);*/
1691
1692     /* Enable menu items that make sense if you're not currently running
1693      a capture. */
1694     main_set_for_capture_in_progress(FALSE);
1695     set_capture_if_dialog_for_capture_in_progress(FALSE);
1696
1697     /* Restore the standard title bar message */
1698     /* (just in case we have trouble opening the capture file). */
1699     main_set_window_name("The Wireshark Network Analyzer");
1700
1701     if(icon_list == NULL) {
1702         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1703     }
1704     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1705
1706     /* We don't have loaded the capture file, this will be done later.
1707      * For now we still have simply a blank screen. */
1708
1709     if(global_capture_opts.quit_after_cap) {
1710         /* command line asked us to quit after the capture */
1711         /* don't pop up a dialog to ask for unsaved files etc. */
1712         main_do_quit();
1713     }
1714 }
1715
1716 static void
1717 main_capture_cb_capture_stopping(capture_options *capture_opts _U_)
1718 {
1719     capture_stopping = TRUE;
1720     set_menus_for_capture_stopping();
1721 #ifdef HAVE_LIBPCAP
1722     set_toolbar_for_capture_stopping();
1723
1724     set_capture_if_dialog_for_capture_stopping();
1725 #endif
1726 }
1727
1728 static void
1729 main_capture_cb_capture_failed(capture_options *capture_opts _U_)
1730 {
1731     static GList *icon_list = NULL;
1732
1733     /* Capture isn't stopping any more. */
1734     capture_stopping = FALSE;
1735
1736     /* the capture failed before the first packet was captured
1737        reset title, menus and icon */
1738
1739     main_set_window_name("The Wireshark Network Analyzer");
1740
1741     main_set_for_capture_in_progress(FALSE);
1742     set_capture_if_dialog_for_capture_in_progress(FALSE);
1743
1744     main_set_for_capture_file(FALSE);
1745
1746     if(icon_list == NULL) {
1747         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1748     }
1749     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1750
1751
1752     if(global_capture_opts.quit_after_cap) {
1753         /* command line asked us to quit after the capture */
1754         /* don't pop up a dialog to ask for unsaved files etc. */
1755         main_do_quit();
1756     }
1757 }
1758 #endif  /* HAVE_LIBPCAP */
1759
1760 static void
1761 main_cf_cb_packet_selected(gpointer data)
1762 {
1763     capture_file *cf = data;
1764
1765     /* Display the GUI protocol tree and packet bytes.
1766       XXX - why do we dump core if we call "proto_tree_draw()"
1767       before calling "add_byte_views()"? */
1768     add_byte_views(cf->edt, tree_view_gbl, byte_nb_ptr_gbl);
1769     proto_tree_draw(cf->edt->tree, tree_view_gbl);
1770
1771     /* Note: Both string and hex value searches in the packet data produce a non-zero
1772        search_pos if successful */
1773     if(cf->search_in_progress &&
1774       (cf->search_pos != 0 || (cf->string && cf->decode_data))) {
1775         highlight_field(cf->edt->tvb, cf->search_pos,
1776                         (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1777     }
1778
1779     /* A packet is selected. */
1780     set_menus_for_selected_packet(cf);
1781 }
1782
1783 static void
1784 main_cf_cb_packet_unselected(capture_file *cf)
1785 {
1786     /* No packet is being displayed; clear the hex dump pane by getting
1787        rid of all the byte views. */
1788     while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0) != NULL)
1789         gtk_notebook_remove_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0);
1790
1791     /* Add a placeholder byte view so that there's at least something
1792        displayed in the byte view notebook. */
1793     add_byte_tab(byte_nb_ptr_gbl, "", NULL, NULL, tree_view_gbl);
1794
1795     /* And clear the protocol tree display as well. */
1796     proto_tree_draw(NULL, tree_view_gbl);
1797
1798     /* No packet is selected. */
1799     set_menus_for_selected_packet(cf);
1800 }
1801
1802 static void
1803 main_cf_cb_field_unselected(capture_file *cf)
1804 {
1805     set_menus_for_selected_tree_row(cf);
1806 }
1807
1808 static void
1809 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1810 {
1811     switch(event) {
1812     case(cf_cb_file_closing):
1813         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1814         main_cf_cb_file_closing(data);
1815         break;
1816     case(cf_cb_file_closed):
1817         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1818         main_cf_cb_file_closed(data);
1819         break;
1820     case(cf_cb_file_read_started):
1821         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1822         main_cf_cb_file_read_started(data);
1823         break;
1824     case(cf_cb_file_read_finished):
1825         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1826         main_cf_cb_file_read_finished(data);
1827         break;
1828     case(cf_cb_file_reload_started):
1829         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload started");
1830         main_cf_cb_file_read_started(data);
1831         break;
1832     case(cf_cb_file_reload_finished):
1833         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1834         main_cf_cb_file_read_finished(data);
1835         break;
1836     case(cf_cb_file_rescan_started):
1837         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan started");
1838         break;
1839     case(cf_cb_file_rescan_finished):
1840         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan finished");
1841         main_cf_cb_file_rescan_finished(data);
1842         break;
1843     case(cf_cb_file_fast_save_finished):
1844         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Fast save finished");
1845         main_cf_cb_file_rescan_finished(data);
1846         break;
1847     case(cf_cb_packet_selected):
1848         main_cf_cb_packet_selected(data);
1849         break;
1850     case(cf_cb_packet_unselected):
1851         main_cf_cb_packet_unselected(data);
1852         break;
1853     case(cf_cb_field_unselected):
1854         main_cf_cb_field_unselected(data);
1855         break;
1856     case(cf_cb_file_save_started):
1857         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1858         break;
1859     case(cf_cb_file_save_finished):
1860         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1861         break;
1862     case(cf_cb_file_save_failed):
1863         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1864         break;
1865     case(cf_cb_file_save_stopped):
1866         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save stopped");
1867         break;
1868     case(cf_cb_file_export_specified_packets_started):
1869         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets started");
1870         break;
1871     case(cf_cb_file_export_specified_packets_finished):
1872         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets finished");
1873         break;
1874     case(cf_cb_file_export_specified_packets_failed):
1875         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets failed");
1876         break;
1877     case(cf_cb_file_export_specified_packets_stopped):
1878         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets stopped");
1879         break;
1880     default:
1881         g_warning("main_cf_callback: event %u unknown", event);
1882         g_assert_not_reached();
1883     }
1884 }
1885
1886 #ifdef HAVE_LIBPCAP
1887 static void
1888 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1889 {
1890 #ifdef HAVE_GTKOSXAPPLICATION
1891     GtkOSXApplication *theApp;
1892 #endif
1893     switch(event) {
1894     case(capture_cb_capture_prepared):
1895         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1896         main_capture_cb_capture_prepared(capture_opts);
1897         break;
1898     case(capture_cb_capture_update_started):
1899         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1900         main_capture_cb_capture_update_started(capture_opts);
1901 #ifdef HAVE_GTKOSXAPPLICATION
1902         theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1903         gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1904 #endif
1905         break;
1906     case(capture_cb_capture_update_continue):
1907         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1908         break;
1909     case(capture_cb_capture_update_finished):
1910         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1911         main_capture_cb_capture_update_finished(capture_opts);
1912         break;
1913     case(capture_cb_capture_fixed_started):
1914         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1915         main_capture_cb_capture_fixed_started(capture_opts);
1916         break;
1917     case(capture_cb_capture_fixed_continue):
1918         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1919         break;
1920     case(capture_cb_capture_fixed_finished):
1921         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1922         main_capture_cb_capture_fixed_finished(capture_opts);
1923         break;
1924     case(capture_cb_capture_stopping):
1925         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1926         /* Beware: this state won't be called, if the capture child
1927          * closes the capturing on it's own! */
1928 #ifdef HAVE_GTKOSXAPPLICATION
1929         theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1930         gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1931 #endif
1932         main_capture_cb_capture_stopping(capture_opts);
1933         break;
1934     case(capture_cb_capture_failed):
1935         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture failed");
1936         main_capture_cb_capture_failed(capture_opts);
1937         break;
1938     default:
1939         g_warning("main_capture_callback: event %u unknown", event);
1940         g_assert_not_reached();
1941     }
1942 }
1943 #endif
1944
1945 static void
1946 get_gtk_compiled_info(GString *str)
1947 {
1948   g_string_append(str, "with ");
1949   g_string_append_printf(str,
1950 #ifdef GTK_MAJOR_VERSION
1951                     "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1952                     GTK_MICRO_VERSION);
1953 #else
1954                     "GTK+ (version unknown)");
1955 #endif
1956   g_string_append(str, ", ");
1957   /* Cairo */
1958   g_string_append(str, "with Cairo ");
1959   g_string_append(str, CAIRO_VERSION_STRING);
1960   g_string_append(str, ", ");
1961
1962   /* Pango */
1963   g_string_append(str, "with Pango ");
1964   g_string_append(str, PANGO_VERSION_STRING);
1965   g_string_append(str, ", ");
1966
1967
1968 }
1969
1970 static void
1971 get_gui_compiled_info(GString *str)
1972 {
1973   epan_get_compiled_version_info(str);
1974
1975   g_string_append(str, ", ");
1976 #ifdef HAVE_LIBPORTAUDIO
1977 #ifdef PORTAUDIO_API_1
1978   g_string_append(str, "with PortAudio <= V18");
1979 #else /* PORTAUDIO_API_1 */
1980   g_string_append(str, "with ");
1981   g_string_append(str, Pa_GetVersionText());
1982 #endif /* PORTAUDIO_API_1 */
1983 #else /* HAVE_LIBPORTAUDIO */
1984   g_string_append(str, "without PortAudio");
1985 #endif /* HAVE_LIBPORTAUDIO */
1986
1987   g_string_append(str, ", ");
1988 #ifdef HAVE_AIRPCAP
1989   get_compiled_airpcap_version(str);
1990 #else
1991   g_string_append(str, "without AirPcap");
1992 #endif
1993 }
1994
1995 static void
1996 get_gui_runtime_info(GString *str)
1997 {
1998   epan_get_runtime_version_info(str);
1999
2000 #ifdef HAVE_AIRPCAP
2001   g_string_append(str, ", ");
2002   get_runtime_airpcap_version(str);
2003 #endif
2004
2005   if(u3_active()) {
2006     g_string_append(str, ", ");
2007     u3_runtime_info(str);
2008   }
2009 }
2010
2011 static e_prefs *
2012 read_configuration_files(char **gdp_path, char **dp_path)
2013 {
2014   int                  gpf_open_errno, gpf_read_errno;
2015   int                  cf_open_errno, df_open_errno;
2016   int                  gdp_open_errno, gdp_read_errno;
2017   int                  dp_open_errno, dp_read_errno;
2018   char                *gpf_path, *pf_path;
2019   char                *cf_path, *df_path;
2020   int                  pf_open_errno, pf_read_errno;
2021   e_prefs             *prefs_p;
2022
2023   /* load the decode as entries of this profile */
2024   load_decode_as_entries();
2025
2026   /* Read the preference files. */
2027   prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2028                      &pf_open_errno, &pf_read_errno, &pf_path);
2029
2030   if (gpf_path != NULL) {
2031     if (gpf_open_errno != 0) {
2032       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2033         "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2034         g_strerror(gpf_open_errno));
2035     }
2036     if (gpf_read_errno != 0) {
2037       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2038         "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2039         g_strerror(gpf_read_errno));
2040     }
2041   }
2042   if (pf_path != NULL) {
2043     if (pf_open_errno != 0) {
2044       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2045         "Could not open your preferences file\n\"%s\": %s.", pf_path,
2046         g_strerror(pf_open_errno));
2047     }
2048     if (pf_read_errno != 0) {
2049       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2050         "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2051         g_strerror(pf_read_errno));
2052     }
2053     g_free(pf_path);
2054     pf_path = NULL;
2055   }
2056
2057 #ifdef _WIN32
2058   /* if the user wants a console to be always there, well, we should open one for him */
2059   if (prefs_p->gui_console_open == console_open_always) {
2060     create_console();
2061   }
2062 #endif
2063
2064   /* Read the capture filter file. */
2065   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2066   if (cf_path != NULL) {
2067       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2068         "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2069         g_strerror(cf_open_errno));
2070       g_free(cf_path);
2071   }
2072
2073   /* Read the display filter file. */
2074   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2075   if (df_path != NULL) {
2076       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2077         "Could not open your display filter file\n\"%s\": %s.", df_path,
2078         g_strerror(df_open_errno));
2079       g_free(df_path);
2080   }
2081
2082   /* Read the disabled protocols file. */
2083   read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
2084                             dp_path, &dp_open_errno, &dp_read_errno);
2085   if (*gdp_path != NULL) {
2086     if (gdp_open_errno != 0) {
2087       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2088         "Could not open global disabled protocols file\n\"%s\": %s.",
2089         *gdp_path, g_strerror(gdp_open_errno));
2090     }
2091     if (gdp_read_errno != 0) {
2092       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2093         "I/O error reading global disabled protocols file\n\"%s\": %s.",
2094         *gdp_path, g_strerror(gdp_read_errno));
2095     }
2096     g_free(*gdp_path);
2097     *gdp_path = NULL;
2098   }
2099   if (*dp_path != NULL) {
2100     if (dp_open_errno != 0) {
2101       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2102         "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
2103         g_strerror(dp_open_errno));
2104     }
2105     if (dp_read_errno != 0) {
2106       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2107         "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
2108         g_strerror(dp_read_errno));
2109     }
2110     g_free(*dp_path);
2111     *dp_path = NULL;
2112   }
2113
2114   return prefs_p;
2115 }
2116
2117 /*  Check if there's something important to tell the user during startup.
2118  *  We want to do this *after* showing the main window so that any windows
2119  *  we pop up will be above the main window.
2120  */
2121 static void
2122 #ifdef _WIN32
2123 check_and_warn_user_startup(gchar *cf_name)
2124 #else
2125 check_and_warn_user_startup(gchar *cf_name _U_)
2126 #endif
2127 {
2128   gchar               *cur_user, *cur_group;
2129   gpointer             priv_warning_dialog;
2130
2131   /* Tell the user not to run as root. */
2132   if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2133     cur_user = get_cur_username();
2134     cur_group = get_cur_groupname();
2135     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2136       "Running as user \"%s\" and group \"%s\".\n"
2137       "This could be dangerous.\n\n"
2138       "If you're running Wireshark this way in order to perform live capture, "
2139       "you may want to be aware that there is a better way documented at\n"
2140       "http://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
2141     g_free(cur_user);
2142     g_free(cur_group);
2143     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2144     simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2145   }
2146
2147 #ifdef _WIN32
2148   /* Warn the user if npf.sys isn't loaded. */
2149   if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2150     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2151       "The NPF driver isn't running.  You may have trouble\n"
2152       "capturing or listing interfaces.");
2153     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2154     simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2155   }
2156 #endif
2157
2158 }
2159
2160
2161 /* And now our feature presentation... [ fade to music ] */
2162 int
2163 main(int argc, char *argv[])
2164 {
2165   char                *init_progfile_dir_error;
2166   char                *s;
2167   int                  opt;
2168   gboolean             arg_error = FALSE;
2169
2170   extern int           info_update_freq;  /* Found in about_dlg.c. */
2171   const gchar         *filter;
2172
2173 #ifdef _WIN32
2174   WSADATA              wsaData;
2175 #endif  /* _WIN32 */
2176
2177   char                *rf_path;
2178   int                  rf_open_errno;
2179   char                *gdp_path, *dp_path;
2180   int                  err;
2181 #ifdef HAVE_LIBPCAP
2182   gboolean             start_capture = FALSE;
2183   gboolean             list_link_layer_types = FALSE;
2184   GList               *if_list;
2185   gchar               *err_str;
2186 #else
2187   gboolean             capture_option_specified = FALSE;
2188 #ifdef _WIN32
2189 #ifdef HAVE_AIRPCAP
2190   gchar               *err_str;
2191 #endif
2192 #endif
2193 #endif
2194   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2195   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL, *dfilter = NULL, *jfilter = NULL;
2196   dfilter_t           *rfcode = NULL;
2197   gboolean             rfilter_parse_failed = FALSE;
2198   e_prefs             *prefs_p;
2199   char                 badopt;
2200   GtkWidget           *splash_win = NULL;
2201   GLogLevelFlags       log_flags;
2202   guint                go_to_packet = 0;
2203   gboolean             jump_backwards = FALSE;
2204   dfilter_t           *jump_to_filter = NULL;
2205   int                  optind_initial;
2206   int                  status;
2207 #ifdef HAVE_GTKOSXAPPLICATION
2208   GtkOSXApplication   *theApp;
2209 #endif
2210
2211 #ifdef HAVE_LIBPCAP
2212 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2213 #define OPTSTRING_B "B:"
2214 #else
2215 #define OPTSTRING_B ""
2216 #endif  /* _WIN32 or HAVE_PCAP_CREATE */
2217 #else /* HAVE_LIBPCAP */
2218 #define OPTSTRING_B ""
2219 #endif  /* HAVE_LIBPCAP */
2220
2221 #ifdef HAVE_PCAP_CREATE
2222 #define OPTSTRING_I "I"
2223 #else
2224 #define OPTSTRING_I ""
2225 #endif
2226
2227 #define 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:"
2228
2229   static const char optstring[] = OPTSTRING;
2230
2231   /* Set the C-language locale to the native environment. */
2232   setlocale(LC_ALL, "");
2233 #ifdef _WIN32
2234   arg_list_utf_16to8(argc, argv);
2235 #endif /* _WIN32 */
2236
2237   /*
2238    * Get credential information for later use, and drop privileges
2239    * before doing anything else.
2240    * Let the user know if anything happened.
2241    */
2242   init_process_policies();
2243   relinquish_special_privs_perm();
2244
2245   /*
2246    * Attempt to get the pathname of the executable file.
2247    */
2248   init_progfile_dir_error = init_progfile_dir(argv[0], main);
2249
2250   /* initialize the funnel mini-api */
2251   initialize_funnel_ops();
2252
2253   AirPDcapInitContext(&airpdcap_ctx);
2254
2255 #ifdef _WIN32
2256   /* Load wpcap if possible. Do this before collecting the run-time version information */
2257   load_wpcap();
2258
2259   /* ... and also load the packet.dll from wpcap */
2260   wpcap_packet_load();
2261
2262 #ifdef HAVE_AIRPCAP
2263   /* Load the airpcap.dll.  This must also be done before collecting
2264    * run-time version information. */
2265   airpcap_dll_ret_val = load_airpcap();
2266
2267   switch (airpcap_dll_ret_val) {
2268   case AIRPCAP_DLL_OK:
2269     /* load the airpcap interfaces */
2270     airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2271
2272     if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2273       if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2274         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2275         g_free(err_str);
2276       }
2277       airpcap_if_active = NULL;
2278
2279     } else {
2280
2281       /* select the first ad default (THIS SHOULD BE CHANGED) */
2282       airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2283           }
2284     break;
2285 #if 0
2286     /*
2287      * XXX - Maybe we need to warn the user if one of the following happens???
2288      */
2289     case AIRPCAP_DLL_OLD:
2290       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2291       break;
2292
2293     case AIRPCAP_DLL_ERROR:
2294       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2295       break;
2296
2297     case AIRPCAP_DLL_NOT_FOUND:
2298       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2299       break;
2300 #endif
2301   }
2302 #endif /* HAVE_AIRPCAP */
2303
2304   /* Start windows sockets */
2305   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2306 #endif  /* _WIN32 */
2307
2308   profile_store_persconffiles (TRUE);
2309
2310   /* Assemble the compile-time version information string */
2311   comp_info_str = g_string_new("Compiled ");
2312
2313   get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2314
2315   /* Assemble the run-time version information string */
2316   runtime_info_str = g_string_new("Running ");
2317   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2318
2319   /* Read the profile independent recent file.  We have to do this here so we can */
2320   /* set the profile before it can be set from the command line parameterts */
2321   recent_read_static(&rf_path, &rf_open_errno);
2322   if (rf_path != NULL && rf_open_errno != 0) {
2323     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2324                   "Could not open common recent file\n\"%s\": %s.",
2325                   rf_path, g_strerror(rf_open_errno));
2326   }
2327
2328   /* "pre-scan" the command line parameters, if we have "console only"
2329      parameters.  We do this so we don't start GTK+ if we're only showing
2330      command-line help or version information.
2331
2332      XXX - this pre-scan is done before we start GTK+, so we haven't
2333      run gtk_init() on the arguments.  That means that GTK+ arguments
2334      have not been removed from the argument list; those arguments
2335      begin with "--", and will be treated as an error by getopt().
2336
2337      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2338      error messages. */
2339   opterr = 0;
2340   optind_initial = optind;
2341   while ((opt = getopt(argc, argv, optstring)) != -1) {
2342     switch (opt) {
2343       case 'C':        /* Configuration Profile */
2344         if (profile_exists (optarg, FALSE)) {
2345           set_profile_name (optarg);
2346         } else {
2347           cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2348           exit(1);
2349         }
2350         break;
2351       case 'D':        /* Print a list of capture devices and exit */
2352 #ifdef HAVE_LIBPCAP
2353         if_list = capture_interface_list(&err, &err_str);
2354         if (if_list == NULL) {
2355           switch (err) {
2356           case CANT_GET_INTERFACE_LIST:
2357           case DONT_HAVE_PCAP:
2358             cmdarg_err("%s", err_str);
2359             g_free(err_str);
2360             break;
2361
2362           case NO_INTERFACES_FOUND:
2363             cmdarg_err("There are no interfaces on which a capture can be done");
2364             break;
2365           }
2366           exit(2);
2367         }
2368         capture_opts_print_interfaces(if_list);
2369         free_interface_list(if_list);
2370         exit(0);
2371 #else
2372         capture_option_specified = TRUE;
2373         arg_error = TRUE;
2374 #endif
2375         break;
2376       case 'h':        /* Print help and exit */
2377         print_usage(TRUE);
2378         exit(0);
2379         break;
2380 #ifdef _WIN32
2381       case 'i':
2382         if (strcmp(optarg, "-") == 0)
2383           stdin_capture = TRUE;
2384         break;
2385 #endif
2386       case 'P':        /* Path settings - change these before the Preferences and alike are processed */
2387         status = filesystem_opt(opt, optarg);
2388         if(status != 0) {
2389             cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2390             exit(status);
2391         }
2392         break;
2393       case 'v':        /* Show version and exit */
2394         show_version();
2395         exit(0);
2396         break;
2397       case 'X':
2398         /*
2399          *  Extension command line options have to be processed before
2400          *  we call epan_init() as they are supposed to be used by dissectors
2401          *  or taps very early in the registration process.
2402          */
2403         ex_opt_add(optarg);
2404         break;
2405       case '?':        /* Ignore errors - the "real" scan will catch them. */
2406         break;
2407     }
2408   }
2409
2410   /* Init the "Open file" dialog directory */
2411   /* (do this after the path settings are processed) */
2412
2413   /* Read the profile dependent (static part) of the recent file. */
2414   /* Only the static part of it will be read, as we don't have the gui now to fill the */
2415   /* recent lists which is done in the dynamic part. */
2416   /* We have to do this already here, so command line parameters can overwrite these values. */
2417   recent_read_profile_static(&rf_path, &rf_open_errno);
2418   if (rf_path != NULL && rf_open_errno != 0) {
2419     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2420                   "Could not open recent file\n\"%s\": %s.",
2421                   rf_path, g_strerror(rf_open_errno));
2422   }
2423
2424   if (recent.gui_fileopen_remembered_dir &&
2425       test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2426     set_last_open_dir(recent.gui_fileopen_remembered_dir);
2427   } else {
2428     set_last_open_dir(get_persdatafile_dir());
2429   }
2430
2431   /* Set getopt index back to initial value, so it will start with the
2432      first command line parameter again.  Also reset opterr to 1, so that
2433      error messages are printed by getopt().
2434
2435      XXX - this seems to work on most platforms, but time will tell.
2436      The Single UNIX Specification says "The getopt() function need
2437      not be reentrant", so this isn't guaranteed to work.  The Mac
2438      OS X 10.4[.x] getopt() man page says
2439
2440        In order to use getopt() to evaluate multiple sets of arguments, or to
2441        evaluate a single set of arguments multiple times, the variable optreset
2442        must be set to 1 before the second and each additional set of calls to
2443        getopt(), and the variable optind must be reinitialized.
2444
2445            ...
2446
2447        The optreset variable was added to make it possible to call the getopt()
2448        function multiple times.  This is an extension to the IEEE Std 1003.2
2449        (``POSIX.2'') specification.
2450
2451      which I think comes from one of the other BSDs.
2452
2453      XXX - if we want to control all the command-line option errors, so
2454      that we can display them where we choose (e.g., in a window), we'd
2455      want to leave opterr as 0, and produce our own messages using optopt.
2456      We'd have to check the value of optopt to see if it's a valid option
2457      letter, in which case *presumably* the error is "this option requires
2458      an argument but none was specified", or not a valid option letter,
2459      in which case *presumably* the error is "this option isn't valid".
2460      Some versions of getopt() let you supply a option string beginning
2461      with ':', which means that getopt() will return ':' rather than '?'
2462      for "this option requires an argument but none was specified", but
2463      not all do. */
2464   optind = optind_initial;
2465   opterr = 1;
2466
2467 #if !GLIB_CHECK_VERSION(2,31,0)
2468   g_thread_init(NULL);
2469 #endif
2470
2471   /* Set the current locale according to the program environment.
2472    * We haven't localized anything, but some GTK widgets are localized
2473    * (the file selection dialogue, for example).
2474    * This also sets the C-language locale to the native environment. */
2475   setlocale (LC_ALL, "");
2476
2477   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2478   gtk_init (&argc, &argv);
2479
2480   cf_callback_add(main_cf_callback, NULL);
2481 #ifdef HAVE_LIBPCAP
2482   capture_callback_add(main_capture_callback, NULL);
2483 #endif
2484   cf_callback_add(statusbar_cf_callback, NULL);
2485 #ifdef HAVE_LIBPCAP
2486   capture_callback_add(statusbar_capture_callback, NULL);
2487 #endif
2488
2489   /* Arrange that if we have no console window, and a GLib message logging
2490      routine is called to log a message, we pop up a console window.
2491
2492      We do that by inserting our own handler for all messages logged
2493      to the default domain; that handler pops up a console if necessary,
2494      and then calls the default handler. */
2495
2496   /* We might want to have component specific log levels later ... */
2497
2498   log_flags =
2499             G_LOG_LEVEL_ERROR|
2500             G_LOG_LEVEL_CRITICAL|
2501             G_LOG_LEVEL_WARNING|
2502             G_LOG_LEVEL_MESSAGE|
2503             G_LOG_LEVEL_INFO|
2504             G_LOG_LEVEL_DEBUG|
2505             G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2506
2507   g_log_set_handler(NULL,
2508             log_flags,
2509             console_log_handler, NULL /* user_data */);
2510   g_log_set_handler(LOG_DOMAIN_MAIN,
2511             log_flags,
2512             console_log_handler, NULL /* user_data */);
2513
2514 #ifdef HAVE_LIBPCAP
2515   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2516             log_flags,
2517             console_log_handler, NULL /* user_data */);
2518   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2519             log_flags,
2520             console_log_handler, NULL /* user_data */);
2521
2522   /* Set the initial values in the capture options. This might be overwritten
2523      by preference settings and then again by the command line parameters. */
2524   capture_opts_init(&global_capture_opts, &cfile);
2525 #endif
2526
2527   /* Initialize whatever we need to allocate colors for GTK+ */
2528   colors_init();
2529
2530   /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2531   filter = get_conn_cfilter();
2532   if ( *filter != '\0' ) {
2533     info_update_freq = 1000;  /* Milliseconds */
2534   }
2535
2536   /* We won't come till here, if we had a "console only" command line parameter. */
2537   splash_win = splash_new("Loading Wireshark ...");
2538   if (init_progfile_dir_error != NULL) {
2539     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2540         "Can't get pathname of Wireshark: %s.\n"
2541         "It won't be possible to capture traffic.\n"
2542         "Report this to the Wireshark developers.",
2543         init_progfile_dir_error);
2544     g_free(init_progfile_dir_error);
2545   }
2546
2547   splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2548
2549   /* Register all dissectors; we must do this before checking for the
2550      "-G" flag, as the "-G" flag dumps information registered by the
2551      dissectors, and we must do it before we read the preferences, in
2552      case any dissectors register preferences. */
2553   epan_init(register_all_protocols,register_all_protocol_handoffs,
2554             splash_update, (gpointer) splash_win,
2555             failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2556             write_failure_alert_box);
2557
2558   splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2559
2560   /* Register all tap listeners; we do this before we parse the arguments,
2561      as the "-z" argument can specify a registered tap. */
2562
2563   /* we register the plugin taps before the other taps because
2564      stats_tree taps plugins will be registered as tap listeners
2565      by stats_tree_stat.c and need to registered before that */
2566
2567 #ifdef HAVE_PLUGINS
2568   register_all_plugin_tap_listeners();
2569 #endif
2570
2571   register_all_tap_listeners();
2572
2573   splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2574
2575   prefs_p = read_configuration_files (&gdp_path, &dp_path);
2576   /* Removed thread code:
2577    * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
2578    */
2579
2580   /* this is to keep tap extensions updating once every 3 seconds */
2581   tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2582
2583   splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2584   proto_help_init();
2585   cap_file_init(&cfile);
2586
2587   /* Fill in capture options with values from the preferences */
2588   prefs_to_capture_opts();
2589
2590 /*#ifdef HAVE_LIBPCAP
2591   fill_in_local_interfaces();
2592 #endif*/
2593   /* Now get our args */
2594   while ((opt = getopt(argc, argv, optstring)) != -1) {
2595     switch (opt) {
2596       /*** capture option specific ***/
2597       case 'a':        /* autostop criteria */
2598       case 'b':        /* Ringbuffer option */
2599       case 'c':        /* Capture xxx packets */
2600       case 'f':        /* capture filter */
2601       case 'k':        /* Start capture immediately */
2602       case 'H':        /* Hide capture info dialog box */
2603       case 'p':        /* Don't capture in promiscuous mode */
2604       case 'i':        /* Use interface x */
2605 #ifdef HAVE_PCAP_CREATE
2606       case 'I':        /* Capture in monitor mode, if available */
2607 #endif
2608       case 's':        /* Set the snapshot (capture) length */
2609       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2610       case 'w':        /* Write to capture file xxx */
2611       case 'y':        /* Set the pcap data link type */
2612 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2613       case 'B':        /* Buffer size */
2614 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2615 #ifdef HAVE_LIBPCAP
2616         status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2617                                       &start_capture);
2618         if(status != 0) {
2619             exit(status);
2620         }
2621 #else
2622         capture_option_specified = TRUE;
2623         arg_error = TRUE;
2624 #endif
2625         break;
2626
2627 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2628       case 'K':        /* Kerberos keytab file */
2629         read_keytab_file(optarg);
2630         break;
2631 #endif
2632
2633       /*** all non capture option specific ***/
2634       case 'C':
2635         /* Configuration profile settings were already processed just ignore them this time*/
2636         break;
2637       case 'd':
2638         dfilter = optarg;
2639         break;
2640       case 'j':        /* Search backwards for a matching packet from filter in option J */
2641         jump_backwards = TRUE;
2642         break;
2643       case 'g':        /* Go to packet with the given packet number */
2644         go_to_packet = get_positive_int(optarg, "go to packet");
2645         break;
2646       case 'J':        /* Jump to the first packet which matches the filter criteria */
2647         jfilter = optarg;
2648         break;
2649       case 'l':        /* Automatic scrolling in live capture mode */
2650 #ifdef HAVE_LIBPCAP
2651         auto_scroll_live = TRUE;
2652 #else
2653         capture_option_specified = TRUE;
2654         arg_error = TRUE;
2655 #endif
2656         break;
2657       case 'L':        /* Print list of link-layer types and exit */
2658 #ifdef HAVE_LIBPCAP
2659         list_link_layer_types = TRUE;
2660 #else
2661         capture_option_specified = TRUE;
2662         arg_error = TRUE;
2663 #endif
2664         break;
2665       case 'm':        /* Fixed-width font for the display */
2666         g_free(prefs_p->gui_font_name);
2667         prefs_p->gui_font_name = g_strdup(optarg);
2668         break;
2669       case 'n':        /* No name resolution */
2670         gbl_resolv_flags.mac_name = FALSE;
2671         gbl_resolv_flags.network_name = FALSE;
2672         gbl_resolv_flags.transport_name = FALSE;
2673         gbl_resolv_flags.concurrent_dns = FALSE;
2674         break;
2675       case 'N':        /* Select what types of addresses/port #s to resolve */
2676         badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2677         if (badopt != '\0') {
2678           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2679             badopt);
2680           exit(1);
2681         }
2682         break;
2683       case 'o':        /* Override preference from command line */
2684         switch (prefs_set_pref(optarg)) {
2685         case PREFS_SET_OK:
2686           break;
2687         case PREFS_SET_SYNTAX_ERR:
2688           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2689           exit(1);
2690           break;
2691         case PREFS_SET_NO_SUCH_PREF:
2692           /* not a preference, might be a recent setting */
2693           switch (recent_set_arg(optarg)) {
2694             case PREFS_SET_OK:
2695               break;
2696             case PREFS_SET_SYNTAX_ERR:
2697               /* shouldn't happen, checked already above */
2698               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2699               exit(1);
2700               break;
2701             case PREFS_SET_NO_SUCH_PREF:
2702             case PREFS_SET_OBSOLETE:
2703               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2704                 optarg);
2705               exit(1);
2706               break;
2707             default:
2708               g_assert_not_reached();
2709             }
2710           break;
2711         case PREFS_SET_OBSOLETE:
2712           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2713             optarg);
2714           exit(1);
2715           break;
2716         default:
2717           g_assert_not_reached();
2718         }
2719         break;
2720       case 'P':
2721         /* Path settings were already processed just ignore them this time*/
2722         break;
2723       case 'r':        /* Read capture file xxx */
2724         /* We may set "last_open_dir" to "cf_name", and if we change
2725         "last_open_dir" later, we free the old value, so we have to
2726         set "cf_name" to something that's been allocated. */
2727         cf_name = g_strdup(optarg);
2728         break;
2729       case 'R':        /* Read file filter */
2730         rfilter = optarg;
2731         break;
2732       case 't':        /* Time stamp type */
2733         if (strcmp(optarg, "r") == 0)
2734           timestamp_set_type(TS_RELATIVE);
2735         else if (strcmp(optarg, "a") == 0)
2736           timestamp_set_type(TS_ABSOLUTE);
2737         else if (strcmp(optarg, "ad") == 0)
2738           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2739         else if (strcmp(optarg, "d") == 0)
2740           timestamp_set_type(TS_DELTA);
2741         else if (strcmp(optarg, "dd") == 0)
2742           timestamp_set_type(TS_DELTA_DIS);
2743         else if (strcmp(optarg, "e") == 0)
2744           timestamp_set_type(TS_EPOCH);
2745         else if (strcmp(optarg, "u") == 0)
2746           timestamp_set_type(TS_UTC);
2747         else if (strcmp(optarg, "ud") == 0)
2748           timestamp_set_type(TS_UTC_WITH_DATE);
2749         else {
2750           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2751           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2752           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2753           exit(1);
2754         }
2755         break;
2756       case 'u':        /* Seconds type */
2757         if (strcmp(optarg, "s") == 0)
2758           timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2759         else if (strcmp(optarg, "hms") == 0)
2760           timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2761         else {
2762           cmdarg_err("Invalid seconds type \"%s\"", optarg);
2763           cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2764           exit(1);
2765         }
2766         break;
2767       case 'X':
2768           /* ext ops were already processed just ignore them this time*/
2769           break;
2770       case 'z':
2771         /* We won't call the init function for the stat this soon
2772            as it would disallow MATE's fields (which are registered
2773            by the preferences set callback) from being used as
2774            part of a tap filter.  Instead, we just add the argument
2775            to a list of stat arguments. */
2776         if (!process_stat_cmd_arg(optarg)) {
2777           cmdarg_err("Invalid -z argument.");
2778           cmdarg_err_cont("  -z argument must be one of :");
2779           list_stat_cmd_args();
2780           exit(1);
2781         }
2782         break;
2783       default:
2784       case '?':        /* Bad flag - print usage message */
2785         arg_error = TRUE;
2786         break;
2787     }
2788   }
2789   if (!arg_error) {
2790     argc -= optind;
2791     argv += optind;
2792     if (argc >= 1) {
2793       if (cf_name != NULL) {
2794         /*
2795          * Input file name specified with "-r" *and* specified as a regular
2796          * command-line argument.
2797          */
2798         cmdarg_err("File name specified both with -r and regular argument");
2799         arg_error = TRUE;
2800       } else {
2801         /*
2802          * Input file name not specified with "-r", and a command-line argument
2803          * was specified; treat it as the input file name.
2804          *
2805          * Yes, this is different from tshark, where non-flag command-line
2806          * arguments are a filter, but this works better on GUI desktops
2807          * where a command can be specified to be run to open a particular
2808          * file - yes, you could have "-r" as the last part of the command,
2809          * but that's a bit ugly.
2810          */
2811         cf_name = g_strdup(argv[0]);
2812       }
2813       argc--;
2814       argv++;
2815     }
2816
2817     if (argc != 0) {
2818       /*
2819        * Extra command line arguments were specified; complain.
2820        */
2821       cmdarg_err("Invalid argument: %s", argv[0]);
2822       arg_error = TRUE;
2823     }
2824   }
2825   if (arg_error) {
2826 #ifndef HAVE_LIBPCAP
2827     if (capture_option_specified) {
2828       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2829     }
2830 #endif
2831     print_usage(FALSE);
2832     exit(1);
2833   }
2834
2835 #ifdef HAVE_LIBPCAP
2836   fill_in_local_interfaces();
2837   if (start_capture && list_link_layer_types) {
2838     /* Specifying *both* is bogus. */
2839     cmdarg_err("You can't specify both -L and a live capture.");
2840     exit(1);
2841   }
2842
2843   if (list_link_layer_types) {
2844     /* We're supposed to list the link-layer types for an interface;
2845        did the user also specify a capture file to be read? */
2846     if (cf_name) {
2847       /* Yes - that's bogus. */
2848       cmdarg_err("You can't specify -L and a capture file to be read.");
2849       exit(1);
2850     }
2851     /* No - did they specify a ring buffer option? */
2852     if (global_capture_opts.multi_files_on) {
2853       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2854       exit(1);
2855     }
2856   } else {
2857     /* We're supposed to do a live capture; did the user also specify
2858        a capture file to be read? */
2859     if (start_capture && cf_name) {
2860       /* Yes - that's bogus. */
2861       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2862       exit(1);
2863     }
2864
2865     /* No - was the ring buffer option specified and, if so, does it make
2866        sense? */
2867     if (global_capture_opts.multi_files_on) {
2868       /* Ring buffer works only under certain conditions:
2869       a) ring buffer does not work with temporary files;
2870       b) real_time_mode and multi_files_on are mutually exclusive -
2871          real_time_mode takes precedence;
2872       c) it makes no sense to enable the ring buffer if the maximum
2873          file size is set to "infinite". */
2874       if (global_capture_opts.save_file == NULL) {
2875         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2876         global_capture_opts.multi_files_on = FALSE;
2877       }
2878       if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2879         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2880         /* XXX - this must be redesigned as the conditions changed */
2881       }
2882     }
2883   }
2884
2885   if (start_capture || list_link_layer_types) {
2886     /* Did the user specify an interface to use? */
2887     if (!capture_opts_trim_iface(&global_capture_opts,
2888         (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2889         exit(2);
2890     }
2891   }
2892
2893   if (list_link_layer_types) {
2894     /* Get the list of link-layer types for the capture devices. */
2895     if_capabilities_t *caps;
2896     guint i;
2897     interface_t device;
2898     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2899
2900       device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2901       if (device.selected) {
2902 #if defined(HAVE_PCAP_CREATE)
2903         caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str);
2904 #else
2905         caps = capture_get_if_capabilities(device.name, FALSE, &err_str);
2906 #endif
2907         if (caps == NULL) {
2908           cmdarg_err("%s", err_str);
2909           g_free(err_str);
2910           exit(2);
2911         }
2912         if (caps->data_link_types == NULL) {
2913           cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
2914           exit(2);
2915         }
2916 #if defined(HAVE_PCAP_CREATE)
2917         capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
2918 #else
2919         capture_opts_print_if_capabilities(caps, device.name, FALSE);
2920 #endif
2921         free_if_capabilities(caps);
2922       }
2923     }
2924     exit(0);
2925   }
2926
2927   capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2928   capture_opts_trim_ring_num_files(&global_capture_opts);
2929 #endif /* HAVE_LIBPCAP */
2930
2931   /* Notify all registered modules that have had any of their preferences
2932      changed either from one of the preferences file or from the command
2933      line that their preferences have changed. */
2934   prefs_apply_all();
2935
2936 #ifdef HAVE_LIBPCAP
2937   if ((global_capture_opts.num_selected == 0) &&
2938       (prefs.capture_device != NULL)) {
2939     guint i;
2940     interface_t device;
2941     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2942       device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2943       if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
2944         device.selected = TRUE;
2945         global_capture_opts.num_selected++;
2946         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
2947         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
2948         break;
2949       }
2950     }
2951   }
2952 #endif
2953
2954   /* disabled protocols as per configuration file */
2955   if (gdp_path == NULL && dp_path == NULL) {
2956     set_disabled_protos_list();
2957   }
2958
2959   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2960
2961   /* read in rc file from global and personal configuration paths. */
2962   rc_file = get_datafile_path(RC_FILE);
2963 #if GTK_CHECK_VERSION(3,0,0)
2964   /* XXX resolve later */
2965 #else
2966   gtk_rc_parse(rc_file);
2967   g_free(rc_file);
2968   rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2969   gtk_rc_parse(rc_file);
2970 #endif
2971   g_free(rc_file);
2972
2973   font_init();
2974
2975   macros_init();
2976
2977   stock_icons_init();
2978
2979   /* close the splash screen, as we are going to open the main window now */
2980   splash_destroy(splash_win);
2981
2982   /************************************************************************/
2983   /* Everything is prepared now, preferences and command line was read in */
2984
2985   /* Pop up the main window. */
2986   create_main_window(pl_size, tv_size, bv_size, prefs_p);
2987
2988   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2989   recent_read_dynamic(&rf_path, &rf_open_errno);
2990   if (rf_path != NULL && rf_open_errno != 0) {
2991     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2992           "Could not open recent file\n\"%s\": %s.",
2993           rf_path, g_strerror(rf_open_errno));
2994   }
2995
2996   color_filters_enable(recent.packet_list_colorize);
2997
2998   /* rearrange all the widgets as we now have all recent settings ready for this */
2999   main_widgets_rearrange();
3000
3001   /* Fill in column titles.  This must be done after the top level window
3002      is displayed.
3003
3004      XXX - is that still true, with fixed-width columns? */
3005
3006   menu_recent_read_finished();
3007 #ifdef HAVE_LIBPCAP
3008   main_auto_scroll_live_changed(auto_scroll_live);
3009 #endif
3010
3011   switch (user_font_apply()) {
3012   case FA_SUCCESS:
3013       break;
3014   case FA_FONT_NOT_RESIZEABLE:
3015       /* "user_font_apply()" popped up an alert box. */
3016       /* turn off zooming - font can't be resized */
3017   case FA_FONT_NOT_AVAILABLE:
3018       /* XXX - did we successfully load the un-zoomed version earlier?
3019       If so, this *probably* means the font is available, but not at
3020       this particular zoom level, but perhaps some other failure
3021       occurred; I'm not sure you can determine which is the case,
3022       however. */
3023       /* turn off zooming - zoom level is unavailable */
3024   default:
3025       /* in any other case than FA_SUCCESS, turn off zooming */
3026       recent.gui_zoom_level = 0;
3027       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
3028   }
3029
3030   dnd_init(top_level);
3031
3032   color_filters_init();
3033   decode_as_init();
3034 #ifdef HAVE_LIBPCAP
3035   capture_filter_init();
3036 #endif
3037
3038   /* the window can be sized only, if it's not already shown, so do it now! */
3039   main_load_window_geometry(top_level);
3040
3041   g_timeout_add(info_update_freq, resolv_update_cb, NULL);
3042
3043   if (dfilter) {
3044     GtkWidget *filter_te;
3045     filter_te = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY)));
3046     gtk_entry_set_text(GTK_ENTRY(filter_te), dfilter);
3047
3048     /* Run the display filter so it goes in effect. */
3049     main_filter_packets(&cfile, dfilter, FALSE);
3050   }
3051
3052   /* If we were given the name of a capture file, read it in now;
3053      we defer it until now, so that, if we can't open it, and pop
3054      up an alert box, the alert box is more likely to come up on
3055      top of the main window - but before the preference-file-error
3056      alert box, so, if we get one of those, it's more likely to come
3057      up on top of us. */
3058   if (cf_name) {
3059     show_main_window(TRUE);
3060     check_and_warn_user_startup(cf_name);
3061     if (rfilter != NULL) {
3062       if (!dfilter_compile(rfilter, &rfcode)) {
3063         bad_dfilter_alert_box(top_level, rfilter);
3064         rfilter_parse_failed = TRUE;
3065       }
3066     }
3067     if (!rfilter_parse_failed) {
3068       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
3069         /* "cf_open()" succeeded, so it closed the previous
3070            capture file, and thus destroyed any previous read filter
3071            attached to "cf". */
3072
3073         cfile.rfcode = rfcode;
3074         /* Open stat windows; we do so after creating the main window,
3075            to avoid GTK warnings, and after successfully opening the
3076            capture file, so we know we have something to compute stats
3077            on, and after registering all dissectors, so that MATE will
3078            have registered its field array and we can have a tap filter
3079            with one of MATE's late-registered fields as part of the
3080            filter. */
3081         start_requested_stats();
3082
3083         /* Read the capture file. */
3084         switch (cf_read(&cfile, FALSE)) {
3085
3086         case CF_READ_OK:
3087         case CF_READ_ERROR:
3088           /* Just because we got an error, that doesn't mean we were unable
3089              to read any of the file; we handle what we could get from the
3090              file. */
3091           /* if the user told us to jump to a specific packet, do it now */
3092           if(go_to_packet != 0) {
3093             /* Jump to the specified frame number, kept for backward
3094                compatibility. */
3095             cf_goto_frame(&cfile, go_to_packet);
3096           } else if (jfilter != NULL) {
3097             /* try to compile given filter */
3098             if (!dfilter_compile(jfilter, &jump_to_filter)) {
3099               bad_dfilter_alert_box(top_level, jfilter);
3100             } else {
3101               /* Filter ok, jump to the first packet matching the filter
3102                  conditions. Default search direction is forward, but if
3103                  option d was given, search backwards */
3104               cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
3105             }
3106           }
3107           break;
3108
3109         case CF_READ_ABORTED:
3110           /* Exit now. */
3111           exit(0);
3112           break;
3113         }
3114
3115         /* If the filename is not the absolute path, prepend the current dir. This happens
3116            when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
3117         if (!g_path_is_absolute(cf_name)) {
3118           char *old_cf_name = cf_name;
3119           char *pwd = g_get_current_dir();
3120           cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
3121           g_free(old_cf_name);
3122           g_free(pwd);
3123         }
3124
3125         /* Save the name of the containing directory specified in the
3126            path name, if any; we can write over cf_name, which is a
3127            good thing, given that "get_dirname()" does write over its
3128            argument. */
3129         s = get_dirname(cf_name);
3130         set_last_open_dir(s);
3131         g_free(cf_name);
3132         cf_name = NULL;
3133       } else {
3134         if (rfcode != NULL)
3135           dfilter_free(rfcode);
3136         cfile.rfcode = NULL;
3137         show_main_window(FALSE);
3138         /* Don't call check_and_warn_user_startup(): we did it above */
3139         main_set_for_capture_in_progress(FALSE);
3140         set_capture_if_dialog_for_capture_in_progress(FALSE);
3141       }
3142     }
3143   } else {
3144 #ifdef HAVE_LIBPCAP
3145     if (start_capture) {
3146       if (global_capture_opts.save_file != NULL) {
3147         /* Save the directory name for future file dialogs. */
3148         /* (get_dirname overwrites filename) */
3149         s = get_dirname(g_strdup(global_capture_opts.save_file));
3150         set_last_open_dir(s);
3151         g_free(s);
3152       }
3153       /* "-k" was specified; start a capture. */
3154       show_main_window(FALSE);
3155       check_and_warn_user_startup(cf_name);
3156
3157       /* If no user interfaces were specified on the command line,
3158          copy the list of selected interfaces to the set of interfaces
3159          to use for this capture. */
3160       if (global_capture_opts.ifaces->len == 0)
3161         collect_ifaces(&global_capture_opts);
3162       if (capture_start(&global_capture_opts)) {
3163         /* The capture started.  Open stat windows; we do so after creating
3164            the main window, to avoid GTK warnings, and after successfully
3165            opening the capture file, so we know we have something to compute
3166            stats on, and after registering all dissectors, so that MATE will
3167            have registered its field array and we can have a tap filter with
3168            one of MATE's late-registered fields as part of the filter. */
3169         start_requested_stats();
3170       }
3171     } else {
3172       show_main_window(FALSE);
3173       check_and_warn_user_startup(cf_name);
3174       main_set_for_capture_in_progress(FALSE);
3175       set_capture_if_dialog_for_capture_in_progress(FALSE);
3176     }
3177
3178     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
3179     if (!start_capture && !global_capture_opts.default_options.cfilter) {
3180       global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
3181     }
3182 #else /* HAVE_LIBPCAP */
3183     show_main_window(FALSE);
3184     check_and_warn_user_startup(cf_name);
3185     main_set_for_capture_in_progress(FALSE);
3186     set_capture_if_dialog_for_capture_in_progress(FALSE);
3187 #endif /* HAVE_LIBPCAP */
3188   }
3189
3190   /* register our pid if we are being run from a U3 device */
3191   u3_register_pid();
3192
3193   profile_store_persconffiles (FALSE);
3194
3195 #ifdef HAVE_GTKOSXAPPLICATION
3196   theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
3197   gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3198   gtk_osxapplication_ready(theApp);
3199 #endif
3200
3201   g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3202
3203 #ifdef HAVE_LIBPCAP
3204   gtk_iface_mon_start();
3205 #endif
3206
3207   /* we'll enter the GTK loop now and hand the control over to GTK ... */
3208   gtk_main();
3209   /* ... back from GTK, we're going down now! */
3210
3211 #ifdef HAVE_LIBPCAP
3212   gtk_iface_mon_stop();
3213 #endif
3214
3215   /* deregister our pid */
3216   u3_deregister_pid();
3217
3218   epan_cleanup();
3219
3220   AirPDcapDestroyContext(&airpdcap_ctx);
3221
3222 #ifdef _WIN32
3223   /* hide the (unresponsive) main window, while asking the user to close the console window */
3224   gtk_widget_hide(top_level);
3225
3226 #ifdef HAVE_GTKOSXAPPLICATION
3227   g_object_unref(theApp);
3228 #endif
3229
3230   /* Shutdown windows sockets */
3231   WSACleanup();
3232
3233   /* For some unknown reason, the "atexit()" call in "create_console()"
3234      doesn't arrange that "destroy_console()" be called when we exit,
3235      so we call it here if a console was created. */
3236   destroy_console();
3237 #endif
3238
3239   exit(0);
3240 }
3241
3242 #ifdef _WIN32
3243
3244 /* We build this as a GUI subsystem application on Win32, so
3245    "WinMain()", not "main()", gets called.
3246
3247    Hack shamelessly stolen from the Win32 port of the GIMP. */
3248 #ifdef __GNUC__
3249 #define _stdcall  __attribute__((stdcall))
3250 #endif
3251
3252 int _stdcall
3253 WinMain (struct HINSTANCE__ *hInstance,
3254          struct HINSTANCE__ *hPrevInstance,
3255          char               *lpszCmdLine,
3256          int                 nCmdShow)
3257 {
3258   INITCOMMONCONTROLSEX comm_ctrl;
3259
3260   /*
3261    * Initialize our DLL search path. MUST be called before LoadLibrary
3262    * or g_module_open.
3263    */
3264   ws_init_dll_search_path();
3265
3266   /* Initialize our controls. Required for native Windows file dialogs. */
3267   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3268   comm_ctrl.dwSize = sizeof(comm_ctrl);
3269   /* Includes the animate, header, hot key, list view, progress bar,
3270    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3271    * up-down controls
3272    */
3273   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3274   InitCommonControlsEx(&comm_ctrl);
3275
3276   /* RichEd20.DLL is needed for filter entries. */
3277   ws_load_library("riched20.dll");
3278
3279   has_console = FALSE;
3280   console_wait = FALSE;
3281   return main (__argc, __argv);
3282 }
3283
3284 /* The code to create and desstroy console windows should not be necessary,
3285    at least as I read the GLib source code, as it looks as if GLib is, on
3286    Win32, *supposed* to create a console window into which to display its
3287    output.
3288
3289    That doesn't happen, however.  I suspect there's something completely
3290    broken about that code in GLib-for-Win32, and that it may be related
3291    to the breakage that forces us to just call "printf()" on the message
3292    rather than passing the message on to "g_log_default_handler()"
3293    (which is the routine that does the aforementioned non-functional
3294    console window creation).  */
3295
3296 /*
3297  * If this application has no console window to which its standard output
3298  * would go, create one.
3299  */
3300 void
3301 create_console(void)
3302 {
3303   if (stdin_capture) {
3304     /* We've been handed "-i -". Don't mess with stdio. */
3305     return;
3306   }
3307
3308   if (!has_console) {
3309     /* We have no console to which to print the version string, so
3310        create one and make it the standard input, output, and error. */
3311
3312     /*
3313      * See if we have an existing console (i.e. we were run from a
3314      * command prompt)
3315      */
3316     if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
3317       if (AllocConsole()) {
3318         console_wait = TRUE;
3319         SetConsoleTitle(_T("Wireshark Debug Console"));
3320       } else {
3321         return;   /* couldn't create console */
3322       }
3323     }
3324
3325     ws_freopen("CONIN$", "r", stdin);
3326     ws_freopen("CONOUT$", "w", stdout);
3327     ws_freopen("CONOUT$", "w", stderr);
3328     fprintf(stdout, "\n");
3329     fprintf(stderr, "\n");
3330
3331     /* Now register "destroy_console()" as a routine to be called just
3332        before the application exits, so that we can destroy the console
3333        after the user has typed a key (so that the console doesn't just
3334        disappear out from under them, giving the user no chance to see
3335        the message(s) we put in there). */
3336     atexit(destroy_console);
3337
3338     /* Well, we have a console now. */
3339     has_console = TRUE;
3340   }
3341 }
3342
3343 static void
3344 destroy_console(void)
3345 {
3346   if (console_wait) {
3347     printf("\n\nPress any key to exit\n");
3348     _getch();
3349   }
3350   FreeConsole();
3351 }
3352 #endif /* _WIN32 */
3353
3354
3355 static void
3356 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3357                     const char *message, gpointer user_data _U_)
3358 {
3359   time_t curr;
3360   struct tm *today;
3361   const char *level;
3362
3363
3364   /* ignore log message, if log_level isn't interesting based
3365      upon the console log preferences.
3366      If the preferences haven't been loaded loaded yet, display the
3367      message anyway.
3368
3369      The default console_log_level preference value is such that only
3370        ERROR, CRITICAL and WARNING level messages are processed;
3371        MESSAGE, INFO and DEBUG level messages are ignored.  */
3372   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3373      prefs.console_log_level != 0) {
3374     return;
3375   }
3376
3377 #ifdef _WIN32
3378   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3379     /* the user wants a console or the application will terminate immediately */
3380     create_console();
3381   }
3382   if (has_console) {
3383     /* For some unknown reason, the above doesn't appear to actually cause
3384        anything to be sent to the standard output, so we'll just splat the
3385        message out directly, just to make sure it gets out. */
3386 #endif
3387     switch(log_level & G_LOG_LEVEL_MASK) {
3388     case G_LOG_LEVEL_ERROR:
3389         level = "Err ";
3390         break;
3391     case G_LOG_LEVEL_CRITICAL:
3392         level = "Crit";
3393         break;
3394     case G_LOG_LEVEL_WARNING:
3395         level = "Warn";
3396         break;
3397     case G_LOG_LEVEL_MESSAGE:
3398         level = "Msg ";
3399         break;
3400     case G_LOG_LEVEL_INFO:
3401         level = "Info";
3402         break;
3403     case G_LOG_LEVEL_DEBUG:
3404         level = "Dbg ";
3405         break;
3406     default:
3407         fprintf(stderr, "unknown log_level %u\n", log_level);
3408         level = NULL;
3409         g_assert_not_reached();
3410     }
3411
3412     /* create a "timestamp" */
3413     time(&curr);
3414     today = localtime(&curr);
3415
3416     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3417             today->tm_hour, today->tm_min, today->tm_sec,
3418             log_domain != NULL ? log_domain : "",
3419             level, message);
3420 #ifdef _WIN32
3421     if(log_level & G_LOG_LEVEL_ERROR) {
3422         /* wait for a key press before the following error handler will terminate the program
3423            this way the user at least can read the error message */
3424         printf("\n\nPress any key to exit\n");
3425         _getch();
3426     }
3427   } else {
3428     /* XXX - on UN*X, should we just use g_log_default_handler()?
3429        We want the error messages to go to the standard output;
3430        on Mac OS X, that will cause them to show up in various
3431        per-user logs accessible through Console (details depend
3432        on whether you're running 10.0 through 10.4 or running
3433        10.5 and later), and, on other UN*X desktop environments,
3434        if they don't show up in some form of console log, that's
3435        a deficiency in that desktop environment.  (Too bad
3436        Windows doesn't set the standard output and error for
3437        GUI apps to something that shows up in such a log.) */
3438     g_log_default_handler(log_domain, log_level, message, user_data);
3439   }
3440 #endif
3441 }
3442
3443
3444 /*
3445  * Helper for main_widgets_rearrange()
3446  */
3447 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3448     gtk_container_remove(GTK_CONTAINER(data), widget);
3449 }
3450
3451 static GtkWidget *main_widget_layout(gint layout_content)
3452 {
3453     switch(layout_content) {
3454     case(layout_pane_content_none):
3455         return NULL;
3456     case(layout_pane_content_plist):
3457         return pkt_scrollw;
3458     case(layout_pane_content_pdetails):
3459         return tv_scrollw;
3460     case(layout_pane_content_pbytes):
3461         return byte_nb_ptr_gbl;
3462     default:
3463         g_assert_not_reached();
3464         return NULL;
3465     }
3466 }
3467
3468
3469 /*
3470  * Rearrange the main window widgets
3471  */
3472 void main_widgets_rearrange(void) {
3473     GtkWidget *first_pane_widget1, *first_pane_widget2;
3474     GtkWidget *second_pane_widget1, *second_pane_widget2;
3475     gboolean split_top_left = FALSE;
3476
3477     /* be a bit faster */
3478     gtk_widget_hide(main_vbox);
3479
3480     /* be sure we don't lose a widget while rearranging */
3481     g_object_ref(G_OBJECT(menubar));
3482     g_object_ref(G_OBJECT(main_tb));
3483     g_object_ref(G_OBJECT(filter_tb));
3484     g_object_ref(G_OBJECT(wireless_tb));
3485     g_object_ref(G_OBJECT(pkt_scrollw));
3486     g_object_ref(G_OBJECT(tv_scrollw));
3487     g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3488     g_object_ref(G_OBJECT(statusbar));
3489     g_object_ref(G_OBJECT(main_pane_v1));
3490     g_object_ref(G_OBJECT(main_pane_v2));
3491     g_object_ref(G_OBJECT(main_pane_h1));
3492     g_object_ref(G_OBJECT(main_pane_h2));
3493     g_object_ref(G_OBJECT(welcome_pane));
3494
3495     /* empty all containers participating */
3496     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3497     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3498     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3499     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3500     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3501
3502     statusbar_widgets_emptying(statusbar);
3503
3504     /* add the menubar always at the top */
3505     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3506
3507     /* main toolbar */
3508     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3509
3510     /* filter toolbar in toolbar area */
3511     if (!prefs.filter_toolbar_show_in_statusbar) {
3512         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3513     }
3514
3515     /* airpcap toolbar */
3516     gtk_box_pack_start(GTK_BOX(main_vbox), wireless_tb, FALSE, TRUE, 1);
3517
3518     /* fill the main layout panes */
3519     switch(prefs.gui_layout_type) {
3520     case(layout_type_5):
3521         main_first_pane  = main_pane_v1;
3522         main_second_pane = main_pane_v2;
3523         split_top_left = FALSE;
3524         break;
3525     case(layout_type_2):
3526         main_first_pane  = main_pane_v1;
3527         main_second_pane = main_pane_h1;
3528         split_top_left = FALSE;
3529         break;
3530     case(layout_type_1):
3531         main_first_pane  = main_pane_v1;
3532         main_second_pane = main_pane_h1;
3533         split_top_left = TRUE;
3534         break;
3535     case(layout_type_4):
3536         main_first_pane  = main_pane_h1;
3537         main_second_pane = main_pane_v1;
3538         split_top_left = FALSE;
3539         break;
3540     case(layout_type_3):
3541         main_first_pane  = main_pane_h1;
3542         main_second_pane = main_pane_v1;
3543         split_top_left = TRUE;
3544         break;
3545     case(layout_type_6):
3546         main_first_pane  = main_pane_h1;
3547         main_second_pane = main_pane_h2;
3548         split_top_left = FALSE;
3549         break;
3550     default:
3551         main_first_pane = NULL;
3552         main_second_pane = NULL;
3553         g_assert_not_reached();
3554     }
3555     if (split_top_left) {
3556         first_pane_widget1 = main_second_pane;
3557         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3558         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3559         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3560     } else {
3561         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3562         first_pane_widget2 = main_second_pane;
3563         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3564         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3565     }
3566     if (first_pane_widget1 != NULL)
3567         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3568     if (first_pane_widget2 != NULL)
3569         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3570     if (second_pane_widget1 != NULL)
3571         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3572     if (second_pane_widget2 != NULL)
3573         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3574
3575     gtk_box_pack_start(GTK_BOX(main_vbox), main_first_pane, TRUE, TRUE, 0);
3576
3577     /* welcome pane */
3578     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3579
3580     /* statusbar */
3581     gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3582
3583     /* filter toolbar in statusbar hbox */
3584     if (prefs.filter_toolbar_show_in_statusbar) {
3585         gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3586     }
3587
3588     /* statusbar widgets */
3589     statusbar_widgets_pack(statusbar);
3590
3591     /* hide widgets on users recent settings */
3592     main_widgets_show_or_hide();
3593
3594     gtk_widget_show(main_vbox);
3595 }
3596
3597 static void
3598 is_widget_visible(GtkWidget *widget, gpointer data)
3599 {
3600     gboolean *is_visible = data;
3601
3602     if (!*is_visible) {
3603         if (gtk_widget_get_visible(widget))
3604             *is_visible = TRUE;
3605     }
3606 }
3607
3608
3609 void
3610 main_widgets_show_or_hide(void)
3611 {
3612     gboolean main_second_pane_show;
3613
3614     if (recent.main_toolbar_show) {
3615         gtk_widget_show(main_tb);
3616     } else {
3617         gtk_widget_hide(main_tb);
3618     }
3619
3620     statusbar_widgets_show_or_hide(statusbar);
3621
3622     if (recent.filter_toolbar_show) {
3623         gtk_widget_show(filter_tb);
3624     } else {
3625         gtk_widget_hide(filter_tb);
3626     }
3627
3628     if (recent.wireless_toolbar_show) {
3629         gtk_widget_show(wireless_tb);
3630     } else {
3631         gtk_widget_hide(wireless_tb);
3632     }
3633
3634     if (recent.packet_list_show && have_capture_file) {
3635         gtk_widget_show(pkt_scrollw);
3636     } else {
3637         gtk_widget_hide(pkt_scrollw);
3638     }
3639
3640     if (recent.tree_view_show && have_capture_file) {
3641         gtk_widget_show(tv_scrollw);
3642     } else {
3643         gtk_widget_hide(tv_scrollw);
3644     }
3645
3646     if (recent.byte_view_show && have_capture_file) {
3647         gtk_widget_show(byte_nb_ptr_gbl);
3648     } else {
3649         gtk_widget_hide(byte_nb_ptr_gbl);
3650     }
3651
3652     if (have_capture_file) {
3653         gtk_widget_show(main_first_pane);
3654     } else {
3655         gtk_widget_hide(main_first_pane);
3656     }
3657
3658     /*
3659      * Is anything in "main_second_pane" visible?
3660      * If so, show it, otherwise hide it.
3661      */
3662     main_second_pane_show = FALSE;
3663     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3664                           &main_second_pane_show);
3665     if (main_second_pane_show) {
3666         gtk_widget_show(main_second_pane);
3667     } else {
3668         gtk_widget_hide(main_second_pane);
3669     }
3670
3671     if (!have_capture_file) {
3672         if(welcome_pane) {
3673             gtk_widget_show(welcome_pane);
3674         }
3675     } else {
3676         gtk_widget_hide(welcome_pane);
3677     }
3678 }
3679
3680
3681 /* called, when the window state changes (minimized, maximized, ...) */
3682 static gboolean
3683 window_state_event_cb (GtkWidget *widget _U_,
3684                        GdkEvent *event,
3685                        gpointer  data _U_)
3686 {
3687     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3688
3689     if( (event->type) == (GDK_WINDOW_STATE)) {
3690         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3691             /* we might have dialogs popped up while we where iconified,
3692                show em now */
3693             display_queued_messages();
3694         }
3695     }
3696     return FALSE;
3697 }
3698
3699
3700
3701 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3702 static gboolean
3703 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3704 {
3705     if (event->keyval == GDK_F8) {
3706         new_packet_list_next();
3707         return TRUE;
3708     } else if (event->keyval == GDK_F7) {
3709         new_packet_list_prev();
3710         return TRUE;
3711     } else if (event->state & NO_SHIFT_MOD_MASK) {
3712         return FALSE; /* Skip control, alt, and other modifiers */
3713     /*
3714      * A comment in gdkkeysyms.h says that it's autogenerated from
3715      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
3716      * don't explicitly say so, isprint() should work as expected
3717      * for values < 127.
3718      */
3719     } else if (isascii(event->keyval) && isprint(event->keyval)) {
3720         /* Forward the keypress on to the display filter entry */
3721         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3722             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3723             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3724         }
3725         return FALSE;
3726     }
3727     return FALSE;
3728 }
3729
3730 static void
3731 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3732 {
3733     GtkAccelGroup *accel;
3734
3735     /* Main window */
3736     top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3737     main_set_window_name("The Wireshark Network Analyzer");
3738
3739     gtk_widget_set_name(top_level, "main window");
3740     g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3741                    NULL);
3742     g_signal_connect(G_OBJECT(top_level), "window_state_event",
3743                          G_CALLBACK(window_state_event_cb), NULL);
3744     g_signal_connect(G_OBJECT(top_level), "key-press-event",
3745                          G_CALLBACK(top_level_key_pressed_cb), NULL );
3746
3747     /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3748     main_vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 1, FALSE);
3749
3750         gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3751     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3752     gtk_widget_show(main_vbox);
3753
3754     /* Menu bar */
3755     menubar = main_menu_new(&accel);
3756
3757 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3758     /* Mac OS X native menus are created and displayed by main_menu_new() */
3759     if(!prefs_p->gui_macosx_style) {
3760 #endif
3761     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3762     gtk_widget_show(menubar);
3763 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3764     }
3765 #endif
3766
3767     /* Main Toolbar */
3768     main_tb = toolbar_new();
3769     gtk_widget_show (main_tb);
3770
3771     /* Filter toolbar */
3772     filter_tb = filter_toolbar_new();
3773
3774     /* Packet list */
3775     pkt_scrollw = new_packet_list_create();
3776     gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3777     gtk_widget_show_all(pkt_scrollw);
3778
3779     /* Tree view */
3780     tv_scrollw = proto_tree_view_new(prefs_p, &tree_view_gbl);
3781     gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3782     gtk_widget_show(tv_scrollw);
3783
3784     g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3785                    "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3786     g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3787                    g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3788     gtk_widget_show(tree_view_gbl);
3789
3790     /* Byte view. */
3791     byte_nb_ptr_gbl = byte_view_new();
3792     gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3793     gtk_widget_show(byte_nb_ptr_gbl);
3794
3795     g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3796                    g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3797
3798     /* Panes for the packet list, tree, and byte view */
3799     main_pane_v1 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3800     gtk_widget_show(main_pane_v1);
3801     main_pane_v2 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3802     gtk_widget_show(main_pane_v2);
3803     main_pane_h1 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3804     gtk_widget_show(main_pane_h1);
3805     main_pane_h2 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3806     gtk_widget_show(main_pane_h2);
3807 #ifdef HAVE_AIRPCAP
3808     wireless_tb = airpcap_toolbar_new();
3809 #else
3810     wireless_tb = ws80211_toolbar_new();
3811 #endif
3812     gtk_widget_show(wireless_tb);
3813
3814     /* status bar */
3815     statusbar = statusbar_new();
3816     gtk_widget_show(statusbar);
3817
3818     /* Pane for the welcome screen */
3819     welcome_pane = welcome_new();
3820     gtk_widget_show(welcome_pane);
3821 }
3822
3823 static void
3824 show_main_window(gboolean doing_work)
3825 {
3826   main_set_for_capture_file(doing_work);
3827
3828   /*** we have finished all init things, show the main window ***/
3829   gtk_widget_show(top_level);
3830
3831   /* the window can be maximized only, if it's visible, so do it after show! */
3832   main_load_window_geometry(top_level);
3833
3834   /* process all pending GUI events before continue */
3835   while (gtk_events_pending()) gtk_main_iteration();
3836
3837   /* Pop up any queued-up alert boxes. */
3838   display_queued_messages();
3839
3840   /* Move the main window to the front, in case it isn't already there */
3841   gdk_window_raise(gtk_widget_get_window(top_level));
3842
3843 #ifdef HAVE_AIRPCAP
3844   airpcap_toolbar_show(wireless_tb);
3845 #endif /* HAVE_AIRPCAP */
3846 }
3847
3848 /* Fill in capture options with values from the preferences */
3849 void
3850 prefs_to_capture_opts(void)
3851 {
3852 #ifdef HAVE_LIBPCAP
3853   /* Set promiscuous mode from the preferences setting. */
3854   /* the same applies to other preferences settings as well. */
3855     global_capture_opts.default_options.promisc_mode = prefs.capture_prom_mode;
3856     global_capture_opts.use_pcapng                   = prefs.capture_pcap_ng;
3857     global_capture_opts.show_info                    = prefs.capture_show_info;
3858     global_capture_opts.real_time_mode               = prefs.capture_real_time;
3859     auto_scroll_live                                 = prefs.capture_auto_scroll;
3860 #endif /* HAVE_LIBPCAP */
3861 }
3862
3863 static void copy_global_profile (const gchar *profile_name)
3864 {
3865     char  *pf_dir_path, *pf_dir_path2, *pf_filename;
3866
3867     if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
3868         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3869             "Can't create directory\n\"%s\":\n%s.",
3870             pf_dir_path, g_strerror(errno));
3871
3872         g_free(pf_dir_path);
3873     }
3874
3875     if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
3876             &pf_dir_path, &pf_dir_path2) == -1) {
3877         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3878             "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
3879             pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
3880
3881         g_free(pf_filename);
3882         g_free(pf_dir_path);
3883         g_free(pf_dir_path2);
3884     }
3885 }
3886
3887 /* Change configuration profile */
3888 void change_configuration_profile (const gchar *profile_name)
3889 {
3890     char  *gdp_path, *dp_path;
3891     char  *rf_path;
3892     int    rf_open_errno;
3893
3894     /* First check if profile exists */
3895     if (!profile_exists(profile_name, FALSE)) {
3896         if (profile_exists(profile_name, TRUE)) {
3897            /* Copy from global profile */
3898             copy_global_profile (profile_name);
3899         } else {
3900             /* No personal and no global profile exists */
3901             return;
3902         }
3903     }
3904
3905     /* Then check if changing to another profile */
3906     if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
3907         return;
3908     }
3909
3910     /* Get the current geometry, before writing it to disk */
3911     main_save_window_geometry(top_level);
3912
3913     if (profile_exists(get_profile_name(), FALSE)) {
3914         /* Write recent file for profile we are leaving, if it still exists */
3915         write_profile_recent();
3916     }
3917
3918     /* Set profile name and update the status bar */
3919     set_profile_name (profile_name);
3920     profile_bar_update ();
3921     filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY);
3922
3923     /* Reset current preferences and apply the new */
3924     prefs_reset();
3925     menu_prefs_reset();
3926
3927     (void) read_configuration_files (&gdp_path, &dp_path);
3928
3929     recent_read_profile_static(&rf_path, &rf_open_errno);
3930     if (rf_path != NULL && rf_open_errno != 0) {
3931         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3932             "Could not open common recent file\n\"%s\": %s.",
3933             rf_path, g_strerror(rf_open_errno));
3934     }
3935     if (recent.gui_fileopen_remembered_dir &&
3936         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3937         set_last_open_dir(recent.gui_fileopen_remembered_dir);
3938     }
3939     timestamp_set_type (recent.gui_time_format);
3940     timestamp_set_seconds_type (recent.gui_seconds_format);
3941     color_filters_enable(recent.packet_list_colorize);
3942
3943     prefs_to_capture_opts();
3944     prefs_apply_all();
3945     macros_post_update();
3946
3947     /* Update window view and redraw the toolbar */
3948     main_titlebar_update();
3949     filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
3950     toolbar_redraw_all();
3951
3952     /* Enable all protocols and disable from the disabled list */
3953     proto_enable_all();
3954     if (gdp_path == NULL && dp_path == NULL) {
3955         set_disabled_protos_list();
3956     }
3957
3958     /* Reload color filters */
3959     color_filters_reload();
3960
3961     /* Reload list of interfaces on welcome page */
3962     welcome_if_panel_reload();
3963
3964     /* Recreate the packet list according to new preferences */
3965     new_packet_list_recreate ();
3966     cfile.cinfo.columns_changed = FALSE; /* Reset value */
3967     user_font_apply();
3968
3969     /* Update menus with new recent values */
3970     menu_recent_read_finished();
3971
3972     /* Reload pane geometry, must be done after recreating the list */
3973     main_pane_load_window_geometry();
3974 }
3975
3976 /** redissect packets and update UI */
3977 void redissect_packets(void)
3978 {
3979     cf_redissect_packets(&cfile);
3980     status_expert_update();
3981 }