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