Provide not only copyright information, but a GPL blurb, in all the
[obnox/wireshark/wip.git] / gtk / main.c
index f23ba8935217e8479c5586de66c33b7b32ce7def..fb786c74b03779d31419fec3dce9cc6d4dafe557 100644 (file)
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_IO_H
-#include <io.h> /* open/close on win32 */
-#endif
-
 #ifdef NEED_STRERROR_H
 #include "strerror.h"
 #endif
@@ -65,9 +61,9 @@
 #include <epan/dfilter/dfilter.h>
 #include <epan/strutil.h>
 #include <epan/addr_resolv.h>
+#include <epan/emem.h>
 
 /* general (not GTK specific) */
-#include "svnversion.h"
 #include "file.h"
 #include "summary.h"
 #include "filters.h"
 #include "register.h"
 #include <epan/prefs-int.h>
 #include "ringbuffer.h"
-#include "../ui_util.h"     /* beware: ui_util.h exists twice! */
+#include "../ui_util.h"
 #include <epan/tap.h>
+#include <epan/stat_cmd_args.h>
 #include "util.h"
 #include "clopts_common.h"
+#include "cmdarg_err.h"
 #include "version_info.h"
 #include "merge.h"
 
 #ifdef HAVE_LIBPCAP
 #include <pcap.h>
-#include "pcap-util.h"
+#include "capture-pcap-util.h"
 #include "capture.h"
+#include "capture_loop.h"
+#include "capture_sync.h"
 #endif
 
 #ifdef _WIN32
 #include "dlg_utils.h"
 #include "gtkglobals.h"
 #include "colors.h"
-#include "ui_util.h"        /* beware: ui_util.h exists twice! */
+#include "gui_utils.h"
 #include "compat_macros.h"
 
 #include "main.h"
 #include "decode_as_dlg.h"
 #include "webbrowser.h"
 #include "capture_dlg.h"
-#if 0
+#ifdef SHOW_WELCOME_PAGE
 #include "../image/eicon3d64.xpm"
 #endif
 #include "capture_ui_utils.h"
+#include "log.h"
+#include "../epan/emem.h"
+#include "file_util.h"
 
 
 
 /*
- * File under personal preferences directory in which GTK settings for
- * Ethereal are stored.
+ * Files under personal and global preferences directories in which
+ * GTK settings for Ethereal are stored.
  */
 #define RC_FILE "gtkrc"
 
@@ -169,13 +172,13 @@ GString *comp_info_str, *runtime_info_str;
 gchar       *ethereal_path = NULL;
 gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
 
+gboolean             capture_child; /* True if this is the child for "-S" */
 #ifdef _WIN32
 static gboolean has_console;   /* TRUE if app has console */
-/*static void create_console(void);*/
 static void destroy_console(void);
+#endif
 static void console_log_handler(const char *log_domain,
     GLogLevelFlags log_level, const char *message, gpointer user_data);
-#endif
 
 #ifdef HAVE_LIBPCAP
 static gboolean list_link_layer_types;
@@ -265,9 +268,6 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
 
     /* Free up the new filter text. */
     g_free(new_filter);
-
-    /* Free up the generated text we were handed. */
-    g_free(text);
 }
 
 void
@@ -307,7 +307,7 @@ void
 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
     int field_id;
-    gchar *proto_abbrev;
+    const gchar *proto_abbrev;
     gpointer  dialog;
 
 
@@ -342,7 +342,7 @@ selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
                     "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
                     "which will save you a lot of editing and will give a consistent look over the pages.",
                     proto_abbrev, proto_abbrev);
-        simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, proto_abbrev);
+        simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
     }
 }
 
@@ -351,7 +351,7 @@ void
 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
     int field_id;
-    gchar *proto_abbrev;
+    const gchar *proto_abbrev;
     gchar *selected_proto_url;
 
 
@@ -403,7 +403,7 @@ get_text_from_packet_list(gpointer data)
            strlen(cfile.cinfo.col_expr_val[column]) != 0) {
            len = strlen(cfile.cinfo.col_expr[column]) +
                  strlen(cfile.cinfo.col_expr_val[column]) + 5;
-           buf = g_malloc0(len);
+           buf = ep_alloc0(len);
            g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
                     cfile.cinfo.col_expr_val[column]);
        }
@@ -999,15 +999,12 @@ main_load_window_geometry(GtkWidget *widget)
 
     window_set_geometry(widget, &geom);
 
-#if GTK_MAJOR_VERSION >= 2
-    /* XXX - rename recent settings? */
-    if (recent.gui_geometry_main_upper_pane)
+    if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
         gtk_paned_set_position(GTK_PANED(main_first_pane),  recent.gui_geometry_main_upper_pane);
-    if (recent.gui_geometry_main_lower_pane)
+    if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
-    if (recent.gui_geometry_status_pane)
+    if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_status_pane)
         gtk_paned_set_position(GTK_PANED(status_pane),      recent.gui_geometry_status_pane);
-#endif
 }
 
 
@@ -1078,35 +1075,45 @@ print_usage(gboolean print_ver) {
 
   FILE *output;
 
+#ifdef _WIN32
+  create_console();
+#endif
+
   if (print_ver) {
     output = stdout;
-    fprintf(output, "This is GNU " PACKAGE " " VERSION
-#ifdef SVNVERSION
-       " (" SVNVERSION ")"
-#endif
-       "\n%s\n\n%s\n",
-       comp_info_str->str, runtime_info_str->str);
+    fprintf(output, "This is "PACKAGE " " VERSION "%s\n"
+        "\n"
+        "%s"
+        "\n"
+       "%s"
+       "\n"
+       "%s",
+       svnversion, get_copyright_info(), comp_info_str->str,
+       runtime_info_str->str);
   } else {
     output = stderr;
   }
 #ifdef HAVE_LIBPCAP
-  fprintf(output, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n",
-         PACKAGE);
-  fprintf(output, "\t[ -b <ringbuffer files options> ] ...]\n");
-  fprintf(output, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
-  fprintf(output, "\t[ -i <interface> ] [ -m <medium font> ] [ -N <resolving> ]\n");
-  fprintf(output, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
-  fprintf(output, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
-  fprintf(output, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
-  fprintf(output, "\t[ -w <savefile> ] [ -y <link type> ] [ -z <statistics string> ]\n");
-  fprintf(output, "\t[ <infile> ]\n");
+  fprintf(output, "\n%s [ -vh ] [ -DklLnpQS ] [ -a <capture autostop condition> ] ...\n", PACKAGE);      
+  fprintf(output, "\t[ -b <capture ring buffer option> ] ...\n");
+#ifdef _WIN32
+  fprintf(output, "\t[ -B <capture buffer size> ]\n");
+#endif
+  fprintf(output, "\t[ -c <capture packet count> ] [ -f <capture filter> ]\n");
+  fprintf(output, "\t[ -g <packet number> ] [ -i <capture interface> ] [ -m <font> ]\n");
+  fprintf(output, "\t[ -N <name resolving flags> ] [ -o <preference/recent setting> ] ...\n");
+  fprintf(output, "\t[ -r <infile> ] [ -R <read (display) filter> ] [ -s <capture snaplen> ]\n");
+  fprintf(output, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -y <capture link type> ]\n");
+  fprintf(output, "\t[ -z <statistics> ] [ <infile> ]\n");
 #else
-  fprintf(output, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
-         PACKAGE);
-  fprintf(output, "\t[ -N <resolving> ] [ -o <preference setting> ...\n");
-  fprintf(output, "\t[ -P <packet list height> ] [ -r <infile> ] [ -R <read filter> ]\n");
-  fprintf(output, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
-  fprintf(output, "\t[ -z <statistics string> ] [ <infile> ]\n");
+  fprintf(output, "\n%s [ -vh ] [ -n ] [ -g <packet number> ] [ -m <font> ]\n", PACKAGE);
+  fprintf(output, "\t[ -N <resolving flags> ] [ -o <preference/recent setting> ...\n");
+  fprintf(output, "\t[ -r <infile> ] [ -R <read (display) filter> ]\n");
+  fprintf(output, "\t[ -t <time stamp format> ] [ -z <statistics ] [ <infile> ]\n");
+#endif
+
+#ifdef _WIN32
+  destroy_console();
 #endif
 }
 
@@ -1117,12 +1124,60 @@ show_version(void)
   create_console();
 #endif
 
-  printf(PACKAGE " " VERSION
-#ifdef SVNVERSION
-      " (" SVNVERSION ")"
+  printf(PACKAGE " " VERSION "%s\n"
+         "\n"
+         "%s"
+         "\n"
+         "%s"
+         "\n"
+         "%s",
+      svnversion, get_copyright_info(), comp_info_str->str,
+      runtime_info_str->str);
+
+#ifdef _WIN32
+  destroy_console();
 #endif
-      "\n%s\n\n%s\n",
-      comp_info_str->str, runtime_info_str->str);
+}
+
+/*
+ * Report an error in command-line arguments.
+ * Creates a console on Windows.
+ * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
+ * terminal isn't the standard error?
+ */
+void
+cmdarg_err(const char *fmt, ...)
+{
+  va_list ap;
+
+#ifdef _WIN32
+  create_console();
+#endif
+  va_start(ap, fmt);
+  fprintf(stderr, "ethereal: ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
+}
+
+/*
+ * Report additional information for an error in command-line arguments.
+ * Creates a console on Windows.
+ * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
+ * terminal isn't the standard error?
+ */
+void
+cmdarg_err_cont(const char *fmt, ...)
+{
+  va_list ap;
+
+#ifdef _WIN32
+  create_console();
+#endif
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
 }
 
 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
@@ -1190,12 +1245,9 @@ static void
 set_display_filename(capture_file *cf)
 {
   const gchar *name_ptr;
-  size_t       msg_len;
-  static const gchar done_fmt[] = " File: %s %s %02u:%02u:%02u";
-  gchar       *done_msg;
-  gchar       *win_name_fmt = "%s - Ethereal";
-  gchar       *win_name;
+  gchar       *status_msg;
   gchar       *size_str;
+  gchar       *win_name;
 
   name_ptr = cf_get_display_name(cf);
        
@@ -1204,43 +1256,61 @@ set_display_filename(capture_file *cf)
     add_menu_recent_capture_file(cf->filename);
   }
 
-  if (cf->f_len/1024/1024 > 10) {
-    size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
-  } else if (cf->f_len/1024 > 10) {
-    size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
+  /* convert file size */
+  if (cf->f_datalen/1024/1024 > 10) {
+    size_str = g_strdup_printf("%ld MB", cf->f_datalen/1024/1024);
+  } else if (cf->f_datalen/1024 > 10) {
+    size_str = g_strdup_printf("%ld KB", cf->f_datalen/1024);
   } else {
-    size_str = g_strdup_printf("%ld Bytes", cf->f_len);
+    size_str = g_strdup_printf("%ld Bytes", cf->f_datalen);
   }
 
-  done_msg = g_strdup_printf(done_fmt, name_ptr, size_str,
-    cf->esec/3600, cf->esec%3600/60, cf->esec%60);
+  /* statusbar */
+  status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu", 
+    (cf->filename) ? cf->filename : "", size_str,
+    (long)cf->elapsed_time.secs/3600,
+    (long)cf->elapsed_time.secs%3600/60,
+    (long)cf->elapsed_time.secs%60);
   g_free(size_str);
-  statusbar_push_file_msg(done_msg);
-  g_free(done_msg);
+  statusbar_push_file_msg(status_msg);
+  g_free(status_msg);
 
-  msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
-  win_name = g_malloc(msg_len);
-  snprintf(win_name, msg_len, win_name_fmt, name_ptr);
+  /* window title */
+  win_name = g_strdup_printf("%s - Ethereal", name_ptr);
   set_main_window_name(win_name);
   g_free(win_name);
 }
 
+GtkWidget           *close_dlg = NULL;
 
 static void
-main_cf_cb_file_closed(capture_file *cf)
+main_cf_cb_file_closing(capture_file *cf)
 {
+
+       /* if we have more than 10000 packets, show a splash screen while closing */
+       /* XXX - don't know a better way to decide wether to show or not,
+        * as most of the time is spend in a single eth_clist_clear function, 
+        * so we can't use a progress bar here! */
+       if(cf->count > 10000) {
+               close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sClosing file!%s\n\nPlease wait ...", 
+                       simple_dialog_primary_start(), simple_dialog_primary_end());
+#if GTK_MAJOR_VERSION >= 2
+               gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
+#else
+               gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER);
+#endif
+       }
+
     /* Destroy all windows, which refer to the
        capture file we're closing. */
-    destroy_cfile_wins();
+    destroy_packet_wins();
+    file_save_as_destroy();
 
     /* Clear any file-related status bar messages.
        XXX - should be "clear *ALL* file-related status bar messages;
        will there ever be more than one on the stack? */
     statusbar_pop_file_msg();
 
-    /* go back to "No packets" */
-    packets_bar_update();
-
     /* Restore the standard title bar message. */
     set_main_window_name("The Ethereal Network Analyzer");
 
@@ -1254,6 +1324,20 @@ main_cf_cb_file_closed(capture_file *cf)
 
     /* Set up main window for no capture file. */
     main_set_for_capture_file(FALSE);
+
+    main_window_update();
+}
+
+static void
+main_cf_cb_file_closed(capture_file *cf _U_)
+{
+  if(close_dlg != NULL) {
+    splash_destroy(close_dlg);
+    close_dlg = NULL;
+  }
+
+  /* go back to "No packets" */
+  packets_bar_update();
 }
 
 static void
@@ -1318,7 +1402,21 @@ static void
 main_cf_cb_live_capture_update_started(capture_options *capture_opts)
 {
     gchar *capture_msg;
+    gchar *title;
+
+
+    /* We've done this in "prepared" above, but it will be cleared while
+       switching to the next multiple file. */
+    if(capture_opts->iface) {
+        title = g_strdup_printf("%s: Capturing - Ethereal",
+                            get_interface_descriptive_name(capture_opts->iface));
+    } else {
+        title = g_strdup_printf("Capturing - Ethereal");
+    }
+    set_main_window_name(title);
+    g_free(title);
 
+    set_menus_for_capture_in_progress(TRUE);
 
     /* Enable menu items that make sense if you have some captured
        packets (yes, I know, we don't have any *yet*). */
@@ -1346,29 +1444,36 @@ main_cf_cb_live_capture_update_continue(capture_file *cf)
 
     statusbar_pop_file_msg();
 
-    if (cf->f_len/1024/1024 > 10) {
+    if (cf->f_datalen/1024/1024 > 10) {
         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %ld MB", 
             get_interface_descriptive_name(capture_opts->iface), 
             capture_opts->save_file,
-            cf->f_len/1024/1024);
-    } else if (cf->f_len/1024 > 10) {
+            cf->f_datalen/1024/1024);
+    } else if (cf->f_datalen/1024 > 10) {
         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %ld KB", 
             get_interface_descriptive_name(capture_opts->iface), 
             capture_opts->save_file,
-            cf->f_len/1024);
+            cf->f_datalen/1024);
     } else {
         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %ld Bytes", 
             get_interface_descriptive_name(capture_opts->iface), 
             capture_opts->save_file,
-            cf->f_len);
+            cf->f_datalen);
     }
 
     statusbar_push_file_msg(capture_msg);
 }
 
+GtkWidget * stop_dlg = NULL;
+
 static void
 main_cf_cb_live_capture_update_finished(capture_file *cf)
 {
+       if(stop_dlg != NULL) {
+               simple_dialog_close(stop_dlg);
+               stop_dlg = NULL;
+       }
+
     /* Pop the "<live capture in progress>" message off the status bar. */
     statusbar_pop_file_msg();
 
@@ -1385,6 +1490,12 @@ main_cf_cb_live_capture_update_finished(capture_file *cf)
 
     /* Set up main window for a capture file. */
     main_set_for_capture_file(TRUE);
+
+    if(capture_opts->quit_after_cap) {
+        /* command line asked us to quit after the capture */
+        /* don't pop up a dialog to ask for unsaved files etc. */
+        main_do_quit();
+    }
 }
 
 static void
@@ -1415,6 +1526,11 @@ main_cf_cb_live_capture_fixed_started(capture_options *capture_opts)
 static void
 main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
 {
+       if(stop_dlg != NULL) {
+               simple_dialog_close(stop_dlg);
+               stop_dlg = NULL;
+       }
+
     /* Pop the "<live capture in progress>" message off the status bar. */
     statusbar_pop_file_msg();
 
@@ -1427,9 +1543,39 @@ main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
      a capture. */
     set_menus_for_capture_in_progress(FALSE);
 
+    /* Restore the standard title bar message */
+    /* (just in case we have trouble opening the capture file). */
+    set_main_window_name("The Ethereal Network Analyzer");
+
     /* We don't have loaded the capture file, this will be done later.
      * For now we still have simply a blank screen. */
+
+    if(capture_opts->quit_after_cap) {
+        /* command line asked us to quit after the capture */
+        /* don't pop up a dialog to ask for unsaved files etc. */
+        main_do_quit();
+    }
+}
+
+static void
+main_cf_cb_live_capture_stopping(capture_file *cf _U_)
+{
+#if 0
+       /* XXX - the time to stop the capture has been reduced (this was only a 
+        * problem on Win32 because of the capture piping), so showing a splash 
+        * isn't really necessary any longer. Unfortunately, the GTKClist packet 
+        * list seems to have problems updating after the dialog is closed, so 
+        * this was disabled here. */
+    stop_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sCapture stop!%s\n\nPlease wait ...", 
+               simple_dialog_primary_start(), simple_dialog_primary_end());
+#if GTK_MAJOR_VERSION >= 2
+       gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
+#else
+       gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER);
+#endif
+#endif
 }
+
 #endif
 
 static void
@@ -1498,37 +1644,54 @@ main_cf_cb_file_safe_reload_finished(gpointer data _U_)
     set_menus_for_unsaved_capture_file(FALSE);
 }
 
-void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
+static void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
 {
     switch(event) {
+    case(cf_cb_file_closing):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
+        main_cf_cb_file_closing(data);
+        break;
     case(cf_cb_file_closed):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
         main_cf_cb_file_closed(data);
         break;
     case(cf_cb_file_read_start):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
         main_cf_cb_file_read_start(data);
         break;
     case(cf_cb_file_read_finished):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
         main_cf_cb_file_read_finished(data);
         break;
 #ifdef HAVE_LIBPCAP
     case(cf_cb_live_capture_prepared):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
         main_cf_cb_live_capture_prepared(data);
         break;
     case(cf_cb_live_capture_update_started):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
         main_cf_cb_live_capture_update_started(data);
         break;
     case(cf_cb_live_capture_update_continue):
+               /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
         main_cf_cb_live_capture_update_continue(data);
         break;
     case(cf_cb_live_capture_fixed_started):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
         main_cf_cb_live_capture_fixed_started(data);
         break;
     case(cf_cb_live_capture_update_finished):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
         main_cf_cb_live_capture_update_finished(data);
         break;
     case(cf_cb_live_capture_fixed_finished):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
         main_cf_cb_live_capture_fixed_finished(data);
         break;
+    case(cf_cb_live_capture_stopping):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
+        main_cf_cb_live_capture_stopping(data);
+        break;
 #endif
     case(cf_cb_packet_selected):
         main_cf_cb_packet_selected(data);
@@ -1540,15 +1703,19 @@ void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
         main_cf_cb_field_unselected(data);
         break;
     case(cf_cb_file_safe_started):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
         main_cf_cb_file_safe_started(data);
         break;
     case(cf_cb_file_safe_finished):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
         main_cf_cb_file_safe_finished(data);
         break;
     case(cf_cb_file_safe_reload_finished):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
         main_cf_cb_file_safe_reload_finished(data);
         break;
     case(cf_cb_file_safe_failed):
+               g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
         main_cf_cb_file_safe_failed(data);
         break;
     default:
@@ -1587,12 +1754,6 @@ main(int argc, char *argv[])
   int                  err;
 #ifdef HAVE_LIBPCAP
   gboolean             start_capture = FALSE;
-  GList               *if_list;
-  if_info_t           *if_info;
-  GList               *lt_list, *lt_entry;
-  data_link_info_t    *data_link_info;
-  gchar                err_str[PCAP_ERRBUF_SIZE];
-  gchar               *cant_get_if_list_errstr;
   gboolean             stats_known;
   struct pcap_stat     stats;
 #else
@@ -1605,23 +1766,125 @@ main(int argc, char *argv[])
   e_prefs             *prefs;
   char                 badopt;
   GtkWidget           *splash_win = NULL;
-  gboolean             capture_child; /* True if this is the child for "-S" */
+  GLogLevelFlags       log_flags;
+  guint                go_to_packet = 0;
+  int                  optind_initial;
 
-#define OPTSTRING_INIT "a:b:B:c:f:Hhi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
+#define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:pQr:R:Ss:t:vw:y:z:"
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
-#define OPTSTRING_CHILD "W:Z:"
+#define OPTSTRING_CHILD "Z:"
+#define OPTSTRING_WIN32 "B:"
 #else
-#define OPTSTRING_CHILD "W:"
+#define OPTSTRING_CHILD ""
+#define OPTSTRING_WIN32 ""
 #endif  /* _WIN32 */
 #else
 #define OPTSTRING_CHILD ""
+#define OPTSTRING_WIN32 ""
 #endif  /* HAVE_LIBPCAP */
 
-  char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
-    OPTSTRING_INIT;
+  char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) + sizeof(OPTSTRING_WIN32) - 2] =
+    OPTSTRING_INIT OPTSTRING_WIN32;
+
+  /* initialize memory allocation subsystem */
+  ep_init_chunk();
+  se_init_chunk();
+
+#ifdef _WIN32
+  /* Load wpcap if possible. Do this before collecting the run-time version information */
+  load_wpcap();
+
+  /* ... and also load the packet.dll from wpcap */
+  wpcap_packet_load();
+
+  /* Start windows sockets */
+  WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
+#endif  /* _WIN32 */
+
+  /* Assemble the compile-time version information string */
+  comp_info_str = g_string_new("Compiled ");
+  g_string_append(comp_info_str, "with ");
+  g_string_sprintfa(comp_info_str,
+#ifdef GTK_MAJOR_VERSION
+                    "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
+                    GTK_MICRO_VERSION);
+#else
+                    "GTK+ (version unknown)");
+#endif
+
+  g_string_append(comp_info_str, ", ");
+  get_compiled_version_info(comp_info_str);
+
+  /* Assemble the run-time version information string */
+  runtime_info_str = g_string_new("Running ");
+  get_runtime_version_info(runtime_info_str);
+
+
+  /* "pre-scan" the command line parameters, if we have "console only"
+     parameters.  We do this so we don't start GTK+ if we're only showing
+     command-line help or version information.
+
+     XXX - this pre-scan is doen before we start GTK+, so we haven't
+     run gtk_init() on the arguments.  That means that GTK+ arguments
+     have not been removed from the argument list; those arguments
+     begin with "--", and will be treated as an error by getopt().
+
+     We thus ignore errors - *and* set "opterr" to 0 to suppress the
+     error messages. */
+  opterr = 0;
+  optind_initial = optind;
+  while ((opt = getopt(argc, argv, optstring)) != -1) {
+    switch (opt) {
+      case 'h':        /* Print help and exit */
+        print_usage(TRUE);
+        exit(0);
+        break;
+      case 'v':        /* Show version and exit */
+        show_version();
+        exit(0);
+        break;
+      case '?':        /* Ignore errors - the "real" scan will catch them. */
+        break;
+    }
+  }
 
+  /* Set getopt index back to initial value, so it will start with the
+     first command line parameter again.  Also reset opterr to 1, so that
+     error messages are printed by getopt().
+
+     XXX - this seems to work on most platforms, but time will tell.
+     The Single UNIX Specification says "The getopt() function need
+     not be reentrant", so this isn't guaranteed to work.  The Mac
+     OS X 10.4[.x] getopt() man page says
+
+       In order to use getopt() to evaluate multiple sets of arguments, or to
+       evaluate a single set of arguments multiple times, the variable optreset
+       must be set to 1 before the second and each additional set of calls to
+       getopt(), and the variable optind must be reinitialized.
+
+           ...             
+
+       The optreset variable was added to make it possible to call the getopt()
+       function multiple times.  This is an extension to the IEEE Std 1003.2
+       (``POSIX.2'') specification.
+
+     which I think comes from one of the other BSDs.
+
+     XXX - if we want to control all the command-line option errors, so
+     that we can display them where we choose (e.g., in a window), we'd
+     want to leave opterr as 0, and produce our own messages using optopt.
+     We'd have to check the value of optopt to see if it's a valid option
+     letter, in which case *presumably* the error is "this option requires
+     an argument but none was specified", or not a valid option letter,
+     in which case *presumably* the error is "this option isn't valid".
+     Some versions of getopt() let you supply a option string beginning
+     with ':', which means that getopt() will return ':' rather than '?'
+     for "this option requires an argument but none was specified", but
+     not all do. */
+  optind = optind_initial;
+  opterr = 1;
 
   /* Set the current locale according to the program environment.
    * We haven't localized anything, but some GTK widgets are localized
@@ -1629,7 +1892,7 @@ main(int argc, char *argv[])
    * This also sets the C-language locale to the native environment. */
   gtk_set_locale();
 
-  /* Let GTK get its args */
+  /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
   gtk_init (&argc, &argv);
 
   cf_callback_add(main_cf_callback, NULL);
@@ -1641,25 +1904,42 @@ main(int argc, char *argv[])
 
   ethereal_path = argv[0];
 
-#ifdef _WIN32
   /* Arrange that if we have no console window, and a GLib message logging
      routine is called to log a message, we pop up a console window.
 
      We do that by inserting our own handler for all messages logged
      to the default domain; that handler pops up a console if necessary,
      and then calls the default handler. */
-  g_log_set_handler(NULL,
+
+  /* We might want to have component specific log levels later ... */
+
+  /* the default_log_handler will use stdout, which makes trouble with the */
+  /* capture child, as it uses stdout for it's sync_pipe */
+  /* so do the filtering in the console_log_handler and not here */
+  log_flags = 
                    G_LOG_LEVEL_ERROR|
                    G_LOG_LEVEL_CRITICAL|
                    G_LOG_LEVEL_WARNING|
                    G_LOG_LEVEL_MESSAGE|
                    G_LOG_LEVEL_INFO|
                    G_LOG_LEVEL_DEBUG|
-                   G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION,
-                   console_log_handler, NULL);
-#endif
+                   G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
+
+  g_log_set_handler(NULL,
+                   log_flags,
+                   console_log_handler, NULL /* user_data */);
+  g_log_set_handler(LOG_DOMAIN_MAIN,
+                   log_flags,
+                   console_log_handler, NULL /* user_data */);
 
 #ifdef HAVE_LIBPCAP
+  g_log_set_handler(LOG_DOMAIN_CAPTURE,
+                   log_flags,
+            console_log_handler, NULL /* user_data */);
+  g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
+                   log_flags,
+            console_log_handler, NULL /* user_data */);
+
   /* Set the initial values in the capture_opts. This might be overwritten 
      by preference settings and then again by the command line parameters. */
   capture_opts_init(capture_opts, &cfile);
@@ -1676,27 +1956,14 @@ main(int argc, char *argv[])
   }
 #endif
 
-  /* We want a splash screen only if we're not a child process */
-    /* We also want it only if we're not being run with "-G".
-       XXX - we also don't want it if we're being run with
-       "-h" or "-v", as those are options to run Ethereal and just
-       have it print stuff to the command line.  That would require
-       that we parse the argument list before putting up the splash
-       screen, which means we'd need to do so before reading the
-       preference files, as that could take enough time that we'd
-       want the splash screen up while we're doing that.  Unfortunately,
-       that means we'd have to queue up, for example, "-o" options,
-       so that we apply them *after* reading the preferences, as
-       they're supposed to override saved preferences. */
-  if ((argc < 2 || strcmp(argv[1], "-G") != 0)
+  /* We want a splash screen only if we're not a child process.
+     We won't come till here, if we had a "console only" command line parameter. */
 #ifdef HAVE_LIBPCAP
-      && !capture_child
+  if (!capture_child)
 #endif
-      ) {
     splash_win = splash_new("Loading Ethereal ...");
-  }
 
-  splash_update(splash_win, "Registering dissectors ...");
+  splash_update(splash_win, "Init dissectors ...");
 
   /* Register all dissectors; we must do this before checking for the
      "-G" flag, as the "-G" flag dumps information registered by the
@@ -1705,7 +1972,7 @@ main(int argc, char *argv[])
   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
             failure_alert_box,open_failure_alert_box,read_failure_alert_box);
 
-  splash_update(splash_win, "Registering tap listeners ...");
+  splash_update(splash_win, "Init tap listeners ...");
 
   /* Register all tap listeners; we do this before we parse the arguments,
      as the "-z" argument can specify a registered tap. */
@@ -1726,32 +1993,6 @@ main(int argc, char *argv[])
      We must do that before we read the preferences as well. */
   prefs_register_modules();
 
-  /* If invoked with the "-G" flag, we dump out information based on
-     the argument to the "-G" flag; if no argument is specified,
-     for backwards compatibility we dump out a glossary of display
-     filter symbols.
-
-     We must do this before calling "gtk_init()", because "gtk_init()"
-     tries to open an X display, and we don't want to have to do any X
-     stuff just to do a build.
-
-     Given that we call "gtk_init()" before doing the regular argument
-     list processing, so that it can handle X and GTK+ arguments and
-     remove them from the list at which we look, this means we must do
-     this before doing the regular argument list processing, as well.
-
-     This means that:
-
-       you must give the "-G" flag as the first flag on the command line;
-
-       you must give it as "-G", nothing more, nothing less;
-
-       the first argument after the "-G" flag, if present, will be used
-       to specify the information to dump;
-
-       arguments after that will not be used. */
-  handle_dashG_option(argc, argv, "ethereal");
-
   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
   {
@@ -1880,36 +2121,12 @@ main(int argc, char *argv[])
     g_free(dp_path);
   }
 
-  init_cap_file(&cfile);
+  /* Read the (static part) of the recent file. Only the static part of it will be read, */
+  /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
+  /* We have to do this already here, so command line parameters can overwrite these values. */
+  recent_read_static(&rf_path, &rf_open_errno);
 
-#ifdef _WIN32
-  /* Load wpcap if possible. Do this before collecting the run-time version information */
-  load_wpcap();
-
-  /* ... and also load the packet.dll from wpcap */
-  wpcap_packet_load();
-
-  /* Start windows sockets */
-  WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-#endif  /* _WIN32 */
-
-  /* Assemble the compile-time version information string */
-  comp_info_str = g_string_new("Compiled ");
-  g_string_append(comp_info_str, "with ");
-  g_string_sprintfa(comp_info_str,
-#ifdef GTK_MAJOR_VERSION
-                    "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
-                    GTK_MICRO_VERSION);
-#else
-                    "GTK+ (version unknown)");
-#endif
-
-  g_string_append(comp_info_str, ", ");
-  get_compiled_version_info(comp_info_str);
-
-  /* Assemble the run-time version information string */
-  runtime_info_str = g_string_new("Running ");
-  get_runtime_version_info(runtime_info_str);
+  init_cap_file(&cfile);
 
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
@@ -1929,32 +2146,30 @@ main(int argc, char *argv[])
       case 'w':        /* Write to capture file xxx */
       case 'y':        /* Set the pcap data link type */
 #ifdef _WIN32
+      case 'B':        /* Buffer size */
       /* Hidden option supporting Sync mode */
       case 'Z':        /* Write to pipe FD XXX */
 #endif /* _WIN32 */
 #ifdef HAVE_LIBPCAP
-        capture_opts_add_opt(capture_opts, "ethereal", opt, optarg, &start_capture);
+        capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
 #endif
         break;
-#ifdef HAVE_LIBPCAP
-      /* This is a hidden option supporting Sync mode, so we don't set
-       * the error flags for the user in the non-libpcap case.
-       */
-      case 'W':        /* Write to capture file FD xxx */
-        capture_opts_add_opt(capture_opts, "ethereal", opt, optarg, &start_capture);
-       break;
-#endif
 
       /*** all non capture option specific ***/
-      case 'B':        /* Byte view pane height */
-        bv_size = get_positive_int("ethereal", optarg, "byte view pane height");
+      case 'D':        /* Print a list of capture devices and exit */
+#ifdef HAVE_LIBPCAP
+        capture_opts_list_interfaces();
+        exit(0);
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
+#endif
         break;
-      case 'h':        /* Print help and exit */
-       print_usage(TRUE);
-       exit(0);
+      case 'g':        /* Go to packet */
+        go_to_packet = get_positive_int(optarg, "go to packet");
         break;
       case 'l':        /* Automatic scrolling in live capture mode */
 #ifdef HAVE_LIBPCAP
@@ -1985,30 +2200,48 @@ main(int argc, char *argv[])
           g_resolv_flags = RESOLV_NONE;
         badopt = string_to_name_resolve(optarg, &g_resolv_flags);
         if (badopt != '\0') {
-          fprintf(stderr, "ethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
+          cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
                        badopt);
           exit(1);
         }
         break;
       case 'o':        /* Override preference from command line */
         switch (prefs_set_pref(optarg)) {
-
-       case PREFS_SET_SYNTAX_ERR:
-          fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
+        case PREFS_SET_OK:
+          break;
+        case PREFS_SET_SYNTAX_ERR:
+          cmdarg_err("Invalid -o flag \"%s\"", optarg);
           exit(1);
           break;
-
         case PREFS_SET_NO_SUCH_PREF:
+          /* not a preference, might be a recent setting */
+          switch (recent_set_arg(optarg)) {
+            case PREFS_SET_OK:
+              break;
+            case PREFS_SET_SYNTAX_ERR:
+              /* shouldn't happen, checked already above */
+              cmdarg_err("Invalid -o flag \"%s\"", optarg);
+              exit(1);
+              break;
+            case PREFS_SET_NO_SUCH_PREF:
+            case PREFS_SET_OBSOLETE:
+              cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
+                   optarg);
+              exit(1);
+              break;
+            default:
+              g_assert_not_reached();
+            }
+          break;
         case PREFS_SET_OBSOLETE:
-          fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
+          cmdarg_err("-o flag \"%s\" specifies obsolete preference",
                        optarg);
           exit(1);
           break;
+        default:
+          g_assert_not_reached();
         }
         break;
-      case 'P':        /* Packet list pane height */
-        pl_size = get_positive_int("ethereal", optarg, "packet list pane height");
-        break;
       case 'r':        /* Read capture file xxx */
        /* We may set "last_open_dir" to "cf_name", and if we change
           "last_open_dir" later, we free the old value, so we have to
@@ -2020,41 +2253,30 @@ main(int argc, char *argv[])
         break;
       case 't':        /* Time stamp type */
         if (strcmp(optarg, "r") == 0)
-          set_timestamp_setting(TS_RELATIVE);
+          timestamp_set_type(TS_RELATIVE);
         else if (strcmp(optarg, "a") == 0)
-          set_timestamp_setting(TS_ABSOLUTE);
+          timestamp_set_type(TS_ABSOLUTE);
         else if (strcmp(optarg, "ad") == 0)
-          set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
+          timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
         else if (strcmp(optarg, "d") == 0)
-          set_timestamp_setting(TS_DELTA);
+          timestamp_set_type(TS_DELTA);
         else {
-          fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
-            optarg);
-          fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
-          fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
+          cmdarg_err("Invalid time stamp type \"%s\"", optarg);
+          cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
+          cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
           exit(1);
         }
         break;
-      case 'T':        /* Tree view pane height */
-        tv_size = get_positive_int("ethereal", optarg, "tree view pane height");
-        break;
-      case 'v':        /* Show version and exit */
-        show_version();
-#ifdef _WIN32
-        destroy_console();
-#endif
-        exit(0);
-        break;
       case 'z':
-        /* We won't call the init function for the tap this soon
+        /* We won't call the init function for the stat this soon
            as it would disallow MATE's fields (which are registered
            by the preferences set callback) from being used as
            part of a tap filter.  Instead, we just add the argument
-           to a list of tap arguments. */
-        if (!process_tap_cmd_arg(optarg)) {
-         fprintf(stderr,"ethereal: invalid -z argument.\n");
-         fprintf(stderr,"  -z argument must be one of :\n");
-         list_tap_cmd_args();
+           to a list of stat arguments. */
+        if (!process_stat_cmd_arg(optarg)) {
+         cmdarg_err("Invalid -z argument.");
+         cmdarg_err_cont("  -z argument must be one of :");
+         list_stat_cmd_args();
          exit(1);
        }
         break;
@@ -2072,6 +2294,7 @@ main(int argc, char *argv[])
        * Input file name specified with "-r" *and* specified as a regular
        * command-line argument.
        */
+      cmdarg_err("File name specified both with -r and regular argument");
       arg_error = TRUE;
     } else {
       /*
@@ -2096,14 +2319,14 @@ main(int argc, char *argv[])
     /*
      * Extra command line arguments were specified; complain.
      */
-    fprintf(stderr, "Invalid argument: %s\n", argv[0]);
+    cmdarg_err("Invalid argument: %s", argv[0]);
     arg_error = TRUE;
   }
 
   if (arg_error) {
 #ifndef HAVE_LIBPCAP
     if (capture_option_specified) {
-      fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
+      cmdarg_err("This version of Ethereal was not built with support for capturing packets.");
     }
 #endif
     print_usage(FALSE);
@@ -2113,7 +2336,7 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
   if (start_capture && list_link_layer_types) {
     /* Specifying *both* is bogus. */
-    fprintf(stderr, "ethereal: You can't specify both -L and a live capture.\n");
+    cmdarg_err("You can't specify both -L and a live capture.");
     exit(1);
   }
 
@@ -2122,12 +2345,12 @@ main(int argc, char *argv[])
        did the user also specify a capture file to be read? */
     if (cf_name) {
       /* Yes - that's bogus. */
-      fprintf(stderr, "ethereal: You can't specify -L and a capture file to be read.\n");
+      cmdarg_err("You can't specify -L and a capture file to be read.");
       exit(1);
     }
     /* No - did they specify a ring buffer option? */
     if (capture_opts->multi_files_on) {
-      fprintf(stderr, "ethereal: Ring buffer requested, but a capture isn't being done.\n");
+      cmdarg_err("Ring buffer requested, but a capture isn't being done.");
       exit(1);
     }
   } else {
@@ -2135,7 +2358,7 @@ main(int argc, char *argv[])
        a capture file to be read? */
     if (start_capture && cf_name) {
       /* Yes - that's bogus. */
-      fprintf(stderr, "ethereal: You can't specify both a live capture and a capture file to be read.\n");
+      cmdarg_err("You can't specify both a live capture and a capture file to be read.");
       exit(1);
     }
 
@@ -2149,15 +2372,15 @@ main(int argc, char *argv[])
         c) it makes no sense to enable the ring buffer if the maximum
            file size is set to "infinite". */
       if (capture_opts->save_file == NULL) {
-       fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
+       cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
        capture_opts->multi_files_on = FALSE;
       }
 /*      if (capture_opts->real_time_mode) {
-       fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
+       cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
        capture_opts->multi_files_on = FALSE;
       }*/
       if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
-       fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size or duration were specified.\n");
+       cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
 /* XXX - this must be redesigned as the conditions changed */
 /*     capture_opts->multi_files_on = FALSE;*/
       }
@@ -2166,77 +2389,19 @@ main(int argc, char *argv[])
 
   if (start_capture || list_link_layer_types) {
     /* Did the user specify an interface to use? */
-    if (capture_opts->iface == NULL) {
-      /* No - is a default specified in the preferences file? */
-      if (prefs->capture_device != NULL) {
-          /* Yes - use it. */
-          capture_opts->iface = g_strdup(prefs->capture_device);
-      } else {
-        /* No - pick the first one from the list of interfaces. */
-        if_list = get_interface_list(&err, err_str);
-        if (if_list == NULL) {
-          switch (err) {
-
-          case CANT_GET_INTERFACE_LIST:
-              cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
-              fprintf(stderr, "%s\n", cant_get_if_list_errstr);
-              g_free(cant_get_if_list_errstr);
-              break;
-
-          case NO_INTERFACES_FOUND:
-              fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
-              break;
-          }
-          exit(2);
-        }
-        if_info = if_list->data;       /* first interface */
-        capture_opts->iface = g_strdup(if_info->name);
-        free_interface_list(if_list);
-      }
+    if (!capture_opts_trim_iface(capture_opts, 
+        (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
+        exit(2);
     }
   }
 
   if (list_link_layer_types) {
-    /* Get the list of link-layer types for the capture device. */
-    lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
-    if (lt_list == NULL) {
-      if (err_str[0] != '\0') {
-       fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n"
-         "Please check to make sure you have sufficient permissions, and that\n"
-         "you have the proper interface or pipe specified.\n", err_str);
-      } else
-       fprintf(stderr, "ethereal: The capture device has no data link types.\n");
-      exit(2);
-    }
-    fprintf(stderr, "Data link types (use option -y to set):\n");
-    for (lt_entry = lt_list; lt_entry != NULL;
-         lt_entry = g_list_next(lt_entry)) {
-      data_link_info = lt_entry->data;
-      fprintf(stderr, "  %s", data_link_info->name);
-      if (data_link_info->description != NULL)
-       fprintf(stderr, " (%s)", data_link_info->description);
-      else
-       fprintf(stderr, " (not supported)");
-      putchar('\n');
-    }
-    free_pcap_linktype_list(lt_list);
+    capture_opts_list_link_layer_types(capture_opts);
     exit(0);
   }
 
-  if (capture_opts->has_snaplen) {
-    if (capture_opts->snaplen < 1)
-      capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
-    else if (capture_opts->snaplen < MIN_PACKET_SIZE)
-      capture_opts->snaplen = MIN_PACKET_SIZE;
-  }
-
-  /* Check the value range of the ringbuffer_num_files parameter */
-  if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
-    capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
-#if RINGBUFFER_MIN_NUM_FILES > 0
-  else if (capture_opts->num_files < RINGBUFFER_MIN_NUM_FILES)
-    capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
-#endif
+  capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
+  capture_opts_trim_ring_num_files(capture_opts);
 #endif /* HAVE_LIBPCAP */
 
   /* Notify all registered modules that have had any of their preferences
@@ -2281,8 +2446,8 @@ main(int argc, char *argv[])
   }
 
   /* read in rc file from global and personal configuration paths. */
-  /* XXX - is this a good idea? */
-  gtk_rc_parse(RC_FILE);
+  rc_file = get_datafile_path(RC_FILE);
+  gtk_rc_parse(rc_file);
   rc_file = get_persconffile_path(RC_FILE, FALSE);
   gtk_rc_parse(rc_file);
 
@@ -2327,15 +2492,14 @@ main(int argc, char *argv[])
   /* Everything is prepared now, preferences and command line was read in,
        we are NOT a child window for a synced capture. */
 
-  /* Pop up the main window, and read in a capture file if
-     we were told to. */
+  /* Pop up the main window. */
   create_main_window(pl_size, tv_size, bv_size, prefs);
 
-  /* Read the recent file, as we have the gui now ready for it. */
-  read_recent(&rf_path, &rf_open_errno);
+  /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
+  recent_read_dynamic(&rf_path, &rf_open_errno);
   color_filters_enable(recent.packet_list_colorize);
 
-  /* rearrange all the widgets as we now have the recent settings for this */
+  /* rearrange all the widgets as we now have all recent settings ready for this */
   main_widgets_rearrange();
 
   /* Fill in column titles.  This must be done after the top level window
@@ -2395,14 +2559,14 @@ main(int argc, char *argv[])
            attached to "cf". */
 
         cfile.rfcode = rfcode;
-        /* Open tap windows; we do so after creating the main window,
+        /* Open stat windows; we do so after creating the main window,
            to avoid GTK warnings, and after successfully opening the
-           capture file, so we know we have something to tap, and
-           after registering all dissectors, so that MATE will have
-           registered its field array and we can have a filter with
-           one of MATE's late-registered fields as part of the tap's
+           capture file, so we know we have something to compute stats
+           on, and after registering all dissectors, so that MATE will
+           have registered its field array and we can have a tap filter
+           with one of MATE's late-registered fields as part of the
            filter. */
-        start_requested_taps();
+        start_requested_stats();
 
         /* Read the capture file. */
         switch (cf_read(&cfile)) {
@@ -2412,6 +2576,10 @@ main(int argc, char *argv[])
           /* Just because we got an error, that doesn't mean we were unable
              to read any of the file; we handle what we could get from the
              file. */
+          /* if the user told us to jump to a specific packet, do it now */
+          if(go_to_packet != 0) {
+            cf_goto_frame(&cfile, go_to_packet);
+          }
           break;
 
         case CF_READ_ABORTED:
@@ -2433,6 +2601,7 @@ main(int argc, char *argv[])
         if (rfcode != NULL)
           dfilter_free(rfcode);
         cfile.rfcode = NULL;
+    show_main_window(FALSE);
        set_menus_for_capture_in_progress(FALSE);
       }
     }
@@ -2449,14 +2618,13 @@ main(int argc, char *argv[])
       /* "-k" was specified; start a capture. */
       show_main_window(TRUE);
       if (capture_start(capture_opts)) {
-        /* The capture started.  Open tap windows; we do so after creating
+        /* The capture started.  Open stat windows; we do so after creating
           the main window, to avoid GTK warnings, and after successfully
-          opening the capture file, so we know we have something to tap,
-          and after registering all dissectors, so that MATE will have
-           registered its field array and we can have a filter with
-           one of MATE's late-registered fields as part of the tap's
-           filter. */
-        start_requested_taps();
+          opening the capture file, so we know we have something to compute
+          stats on, and after registering all dissectors, so that MATE will
+          have registered its field array and we can have a tap filter with
+           one of MATE's late-registered fields as part of the filter. */
+        start_requested_stats();
       }
     }
     else {
@@ -2477,12 +2645,17 @@ main(int argc, char *argv[])
 #endif /* HAVE_LIBPCAP */
   }
 
+  /* we'll enter the GTK loop now and hand the control over to GTK ... */
   gtk_main();
+  /* ... back from GTK, we're going down now! */
 
   epan_cleanup();
   g_free(rc_file);
 
 #ifdef _WIN32
+  /* hide the (unresponsive) main window, while asking the user to close the console window */
+  gtk_widget_hide(top_level);
+
   /* Shutdown windows sockets */
   WSACleanup();
 
@@ -2529,14 +2702,14 @@ WinMain (struct HINSTANCE__ *hInstance,
 void
 create_console(void)
 {
-  if (!has_console && prefs.gui_console_open != console_open_never) {
+  if (!has_console) {
     /* We have no console to which to print the version string, so
        create one and make it the standard input, output, and error. */
     if (!AllocConsole())
       return;   /* couldn't create console */
-    freopen("CONIN$", "r", stdin);
-    freopen("CONOUT$", "w", stdout);
-    freopen("CONOUT$", "w", stderr);
+    eth_freopen("CONIN$", "r", stdin);
+    eth_freopen("CONOUT$", "w", stdout);
+    eth_freopen("CONOUT$", "w", stderr);
 
     /* Well, we have a console now. */
     has_console = TRUE;
@@ -2547,18 +2720,26 @@ create_console(void)
        disappear out from under them, giving the user no chance to see
        the message(s) we put in there). */
     atexit(destroy_console);
+
+       if(capture_child) {
+               SetConsoleTitle("Ethereal Capture Child Debug Console");
+       } else {
+               SetConsoleTitle("Ethereal Debug Console");
+       }
   }
 }
 
 static void
 destroy_console(void)
 {
-  if (has_console) {
+  if (has_console && !capture_child) {
     printf("\n\nPress any key to exit\n");
     _getch();
     FreeConsole();
   }
 }
+#endif /* _WIN32 */
+
 
 /* This routine should not be necessary, at least as I read the GLib
    source code, as it looks as if GLib is, on Win32, *supposed* to
@@ -2572,21 +2753,70 @@ destroy_console(void)
    console window creation). */
 static void
 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
-                   const char *message, gpointer user_data)
+                   const char *message, gpointer user_data _U_)
 {
-  create_console();
+  time_t curr;
+  struct tm *today;
+  const char *level;
+
+
+  /* ignore log message, if log_level isn't interesting */
+  if( !(log_level & G_LOG_LEVEL_MASK & prefs.console_log_level)) {
+    return;
+  }
+
+  /* create a "timestamp" */
+  time(&curr);
+  today = localtime(&curr);    
+
+#ifdef _WIN32
+  if (prefs.gui_console_open != console_open_never) {
+    create_console();
+  }
   if (has_console) {
     /* For some unknown reason, the above doesn't appear to actually cause
        anything to be sent to the standard output, so we'll just splat the
        message out directly, just to make sure it gets out. */
-    printf("%s\n", message);
-  } else
+#endif
+    switch(log_level & G_LOG_LEVEL_MASK) {
+    case G_LOG_LEVEL_ERROR:
+        level = "Err ";
+        break;
+    case G_LOG_LEVEL_CRITICAL:
+        level = "Crit";
+        break;
+    case G_LOG_LEVEL_WARNING:
+        level = "Warn";
+        break;
+    case G_LOG_LEVEL_MESSAGE:
+        level = "Msg ";
+        break;
+    case G_LOG_LEVEL_INFO:
+        level = "Info";
+        break;
+    case G_LOG_LEVEL_DEBUG:
+        level = "Dbg ";
+        break;
+    default:
+        fprintf(stderr, "unknown log_level %u\n", log_level);
+        level = NULL;
+        g_assert_not_reached();
+    }
+
+    /* don't use printf (stdout), as the capture child uses stdout for it's sync_pipe */
+    fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
+            today->tm_hour, today->tm_min, today->tm_sec,
+            log_domain != NULL ? log_domain : "",
+            level, message);
+#ifdef _WIN32
+  } else {
     g_log_default_handler(log_domain, log_level, message, user_data);
-}
+  }
 #endif
+}
 
 
-GtkWidget *info_bar_new(void)
+static GtkWidget *info_bar_new(void)
 {
     /* tip: tooltips don't work on statusbars! */
     info_bar = gtk_statusbar_new();
@@ -2601,7 +2831,7 @@ GtkWidget *info_bar_new(void)
     return info_bar;
 }
 
-GtkWidget *packets_bar_new(void)
+static GtkWidget *packets_bar_new(void)
 {
     /* tip: tooltips don't work on statusbars! */
     packets_bar = gtk_statusbar_new();
@@ -2615,11 +2845,11 @@ GtkWidget *packets_bar_new(void)
 /*
  * Helper for main_widgets_rearrange()
  */
-void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
+static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
     gtk_container_remove(GTK_CONTAINER(data), widget);
 }
 
-GtkWidget *main_widget_layout(gint layout_content)
+static GtkWidget *main_widget_layout(gint layout_content)
 {
     switch(layout_content) {
     case(layout_pane_content_none):
@@ -2783,7 +3013,7 @@ is_widget_visible(GtkWidget *widget, gpointer data)
 }
 
 
-#if 0
+#ifdef SHOW_WELCOME_PAGE
 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
    As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
 GtkWidget *
@@ -2900,14 +3130,14 @@ welcome_new(void)
 
     return welcome_scrollw;
 }
-#endif /* 0 */
-
-GtkWidget *
+#else
+static GtkWidget *
 welcome_new(void)
 {
     /* this is just a dummy to fill up window space, simply showing nothing */
     return scrolled_window_new(NULL, NULL);
 }
+#endif