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