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