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