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