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