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