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