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