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