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