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