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