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