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