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