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