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