[H248 3GPP] Add dissection of IP transport package.
[metze/wireshark/wip.git] / wireshark-qt.cpp
index 30a1bce60fe63c446115e5ba5cac7882e255588c..5ad28c59e978b0c33b5fad388dfc63dc57b40200 100644 (file)
@@ -27,9 +27,7 @@
 #include <signal.h>
 #endif
 
-#ifdef HAVE_LIBZ
-#include <zlib.h>       /* to get the libz version number */
-#endif
+#include <locale.h>
 
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
@@ -48,9 +46,8 @@
 #include <wsutil/plugins.h>
 #endif
 #include <wsutil/report_err.h>
-#include <wsutil/u3.h>
-#include <wsutil/ws_diag_control.h>
-#include <wsutil/ws_version_info.h>
+#include <wsutil/unicode-utils.h>
+#include <ws_version_info.h>
 
 #include <epan/addr_resolv.h>
 #include <epan/ex-opt.h>
@@ -58,6 +55,7 @@
 #include <epan/stat_tap_ui.h>
 #include <epan/column.h>
 #include <epan/disabled_protos.h>
+#include <epan/prefs.h>
 
 #ifdef HAVE_KERBEROS
 #include <epan/packet.h>
 #include <epan/dissectors/packet-kerberos.h>
 #endif
 
-#ifdef HAVE_PLUGINS
 #include <codecs/codecs.h>
+
+#ifdef HAVE_EXTCAP
+#include <extcap.h>
 #endif
 
 /* general (not Qt specific) */
 #include "file.h"
-#include "color.h"
-#include "color_filters.h"
-#include "ui/util.h"
+#include "epan/color_filters.h"
 #include "log.h"
 
+#include "epan/rtd_table.h"
+#include "epan/srt_table.h"
+
 #include "ui/alert_box.h"
 #include "ui/console.h"
 #include "ui/iface_lists.h"
 #include "ui/persfilepath_opt.h"
 #include "ui/recent.h"
 #include "ui/simple_dialog.h"
+#include "ui/util.h"
+#include "ui/dissect_opts.h"
+#include "ui/commandline.h"
+#include "ui/capture_ui_utils.h"
 
-#include "ui/qt/simple_dialog.h"
+#include "ui/qt/conversation_dialog.h"
+#include "ui/qt/color_utils.h"
+#include "ui/qt/coloring_rules_dialog.h"
+#include "ui/qt/endpoint_dialog.h"
 #include "ui/qt/main_window.h"
+#include "ui/qt/response_time_delay_dialog.h"
+#include "ui/qt/service_response_time_dialog.h"
+#include "ui/qt/simple_dialog.h"
+#include "ui/qt/simple_statistics_dialog.h"
 #include "ui/qt/splash_overlay.h"
 #include "ui/qt/wireshark_application.h"
 
 #include <QTextCodec>
 #endif
 
-#include "ui/qt/conversation_dialog.h"
-#include "ui/qt/endpoint_dialog.h"
-
-#ifdef HAVE_LIBPCAP
-capture_options global_capture_opts;
-#endif
+#define INIT_FAILED 2
+#define INVALID_CAPABILITY 2
+#define INVALID_LINK_TYPE 2
 
-#ifdef HAVE_AIRPCAP
-int    airpcap_dll_ret_val = -1;
-#endif
-
-GString *comp_info_str, *runtime_info_str;
+//#define DEBUG_STARTUP_TIME 1
+/*
+# Log level
+# Console log level (for debugging)
+# A bitmask of log levels:
+# ERROR    = 4
+# CRITICAL = 8
+# WARNING  = 16
+# MESSAGE  = 32
+# INFO     = 64
+# DEBUG    = 128
+
+*/
+#define DEBUG_STARTUP_TIME_LOGLEVEL 252
 
 /* update the main window */
 void main_window_update(void)
@@ -148,109 +166,6 @@ void main_window_quit(void)
 
 #endif /* HAVE_LIBPCAP */
 
-
-// xxx copied from ../gtk/main.c
-static void
-print_usage(gboolean for_help_option) {
-    FILE *output;
-
-#ifdef _WIN32
-    create_console();
-#endif
-
-    if (for_help_option) {
-        output = stdout;
-        fprintf(output, "Wireshark %s\n"
-                "Interactively dump and analyze network traffic.\n"
-                "See http://www.wireshark.org for more information.\n",
-                get_ws_vcs_version_info());
-    } else {
-        output = stderr;
-    }
-    fprintf(output, "\n");
-    fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
-    fprintf(output, "\n");
-
-#ifdef HAVE_LIBPCAP
-    fprintf(output, "Capture interface:\n");
-    fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
-    fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
-    fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
-    fprintf(output, "  -p                       don't capture in promiscuous mode\n");
-    fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
-    fprintf(output, "  -S                       update packet display when new packets are captured\n");
-    fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
-#ifdef HAVE_PCAP_CREATE
-    fprintf(output, "  -I                       capture in monitor mode, if available\n");
-#endif
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-    fprintf(output, "  -B <buffer size>         size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
-#endif
-    fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
-    fprintf(output, "  -D                       print list of interfaces and exit\n");
-    fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
-    fprintf(output, "\n");
-    fprintf(output, "Capture stop conditions:\n");
-    fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
-    fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
-    fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
-    fprintf(output, "                              files:NUM - stop after NUM files\n");
-    /*fprintf(output, "\n");*/
-    fprintf(output, "Capture output:\n");
-    fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
-    fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
-    fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
-#endif  /* HAVE_LIBPCAP */
-#ifdef HAVE_PCAP_REMOTE
-    fprintf(output, "RPCAP options:\n");
-    fprintf(output, "  -A <user>:<password>     use RPCAP password authentication\n");
-#endif
-    /*fprintf(output, "\n");*/
-    fprintf(output, "Input file:\n");
-    fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
-
-    fprintf(output, "\n");
-    fprintf(output, "Processing:\n");
-    fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
-    fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
-    fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
-
-    fprintf(output, "\n");
-    fprintf(output, "User interface:\n");
-    fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
-    fprintf(output, "  -Y <display filter>      start with the given display filter\n");
-    fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
-    fprintf(output, "  -J <jump filter>         jump to the first packet matching the (display)\n");
-    fprintf(output, "                           filter\n");
-    fprintf(output, "  -j                       search backwards for a matching packet after \"-J\"\n");
-    fprintf(output, "  -m <font>                set the font name used for most text\n");
-    fprintf(output, "  -t a|ad|d|dd|e|r|u|ud    output format of time stamps (def: r: rel. to first)\n");
-    fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
-    fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
-    fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
-
-    fprintf(output, "\n");
-    fprintf(output, "Output:\n");
-    fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
-
-    fprintf(output, "\n");
-    fprintf(output, "Miscellaneous:\n");
-    fprintf(output, "  -h                       display this help and exit\n");
-    fprintf(output, "  -v                       display version info and exit\n");
-    fprintf(output, "  -P <key>:<path>          persconf:path - personal configuration files\n");
-    fprintf(output, "                           persdata:path - personal data files\n");
-    fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
-    fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
-#ifndef _WIN32
-    fprintf(output, "  --display=DISPLAY        X display to use\n");
-#endif
-    fprintf(output, "\nNOTE: Not all options are implemented in the Qt port.\n");
-
-#ifdef _WIN32
-    destroy_console();
-#endif
-}
-
 /*
  * Report an error in command-line arguments.
  * Creates a console on Windows.
@@ -285,7 +200,7 @@ wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
 }
 
 // xxx based from ../gtk/main.c:get_gtk_compiled_info
-static void
+void
 get_wireshark_qt_compiled_info(GString *str)
 {
     g_string_append(str, "with ");
@@ -299,29 +214,20 @@ get_wireshark_qt_compiled_info(GString *str)
     /* Capture libraries */
     g_string_append(str, ", ");
     get_compiled_caplibs_version(str);
-
-    /* LIBZ */
-    g_string_append(str, ", ");
-#ifdef HAVE_LIBZ
-    g_string_append(str, "with libz ");
-#ifdef ZLIB_VERSION
-    g_string_append(str, ZLIB_VERSION);
-#else /* ZLIB_VERSION */
-    g_string_append(str, "(version unknown)");
-#endif /* ZLIB_VERSION */
-#else /* HAVE_LIBZ */
-    g_string_append(str, "without libz");
-#endif /* HAVE_LIBZ */
 }
 
 // xxx copied from ../gtk/main.c
-static void
+void
 get_gui_compiled_info(GString *str)
 {
     epan_get_compiled_version_info(str);
 
     g_string_append(str, ", ");
-    g_string_append(str, "without PortAudio");
+#ifdef QT_MULTIMEDIA_LIB
+    g_string_append(str, "with QtMultimedia");
+#else
+    g_string_append(str, "without QtMultimedia");
+#endif
 
     g_string_append(str, ", ");
 #ifdef HAVE_AIRPCAP
@@ -329,10 +235,12 @@ get_gui_compiled_info(GString *str)
 #else
     g_string_append(str, "without AirPcap");
 #endif
+
+    codec_get_compiled_version_info(str);
 }
 
 // xxx copied from ../gtk/main.c
-static void
+void
 get_wireshark_runtime_info(GString *str)
 {
 #ifdef HAVE_LIBPCAP
@@ -341,11 +249,6 @@ get_wireshark_runtime_info(GString *str)
     get_runtime_caplibs_version(str);
 #endif
 
-    /* zlib */
-#if defined(HAVE_LIBZ) && !defined(_WIN32)
-    g_string_append_printf(str, ", with libz %s", zlibVersion());
-#endif
-
     /* stuff used by libwireshark */
     epan_get_runtime_version_info(str);
 
@@ -353,11 +256,6 @@ get_wireshark_runtime_info(GString *str)
     g_string_append(str, ", ");
     get_runtime_airpcap_version(str);
 #endif
-
-    if(u3_active()) {
-        g_string_append(str, ", ");
-        u3_runtime_info(str);
-    }
 }
 
 #ifdef HAVE_LIBPCAP
@@ -382,7 +280,7 @@ check_and_warn_user_startup(const QString &cf_name)
         "This could be dangerous.\n\n"
         "If you're running Wireshark this way in order to perform live capture, "
         "you may want to be aware that there is a better way documented at\n"
-        "http://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
+        "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
         g_free(cur_user);
         g_free(cur_group);
     }
@@ -430,46 +328,70 @@ reset_library_path(void)
 #endif
 
 /* And now our feature presentation... [ fade to music ] */
-int main(int argc, char *argv[])
+int main(int argc, char *qt_argv[])
 {
     MainWindow *main_w;
 
+#ifdef _WIN32
     int                  opt;
-    gboolean             arg_error = FALSE;
+#endif
+    int                  ret_val = EXIT_SUCCESS;
+    char               **argv = qt_argv;
 
 #ifdef _WIN32
-    WSADATA            wsaData;
+    WSADATA              wsaData;
 #endif  /* _WIN32 */
 
     char                *rf_path;
     int                  rf_open_errno;
     char                *gdp_path, *dp_path;
 #ifdef HAVE_LIBPCAP
-    int                  err;
-    gboolean             start_capture = FALSE;
-    gboolean             list_link_layer_types = FALSE;
-    GList               *if_list;
     gchar               *err_str;
-    int                  status;
 #else
-    gboolean             capture_option_specified = FALSE;
 #ifdef _WIN32
 #ifdef HAVE_AIRPCAP
     gchar               *err_str;
 #endif
 #endif
 #endif
-    e_prefs             *prefs_p;
-    char                 badopt;
-    guint                go_to_packet = 0;
+    gchar               *err_msg = NULL;
+    GString             *comp_info_str = NULL;
+    GString             *runtime_info_str = NULL;
 
     QString              dfilter, read_filter;
-
+    /* Start time in microseconds*/
+    guint64 start_time = g_get_monotonic_time();
+#ifdef DEBUG_STARTUP_TIME
+    /* At least on Windows there is a problem with the loging as the preferences is taken
+     * into account and the preferences are loaded pretty late in the startup process.
+     */
+    prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
+    prefs.gui_console_open = console_open_always;
+#endif /* DEBUG_STARTUP_TIME */
     cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
 
+    // In Qt 5, C strings are treated always as UTF-8 when converted to
+    // QStrings; in Qt 4, the codec must be set to make that happen
+#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
+    // Hopefully we won't have to use QString::fromUtf8() in as many places.
+    QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
+    QTextCodec::setCodecForCStrings(utf8codec);
+    // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
+    QTextCodec::setCodecForTr(utf8codec);
+#endif
+
+    /* Set the C-language locale to the native environment. */
+    setlocale(LC_ALL, "");
+
 #ifdef _WIN32
+    // QCoreApplication clobbers argv. Let's have a local copy.
+    argv = (char **) g_malloc(sizeof(char *) * argc);
+    for (opt = 0; opt < argc; opt++) {
+        argv[opt] = qt_argv[opt];
+    }
+    arg_list_utf_16to8(argc, argv);
     create_app_running_mutex();
-#endif
+#endif /* _WIN32 */
 
     /*
      * Get credential information for later use, and drop privileges
@@ -480,161 +402,15 @@ int main(int argc, char *argv[])
     relinquish_special_privs_perm();
 
     /*
-     * Attempt to get the pathname of the executable file.
+     * Attempt to get the pathname of the directory containing the
+     * executable file.
      */
     /* init_progfile_dir_error = */ init_progfile_dir(argv[0],
-        (progfile_main_t) get_gui_compiled_info);
+        (int (*)(int, char **)) get_gui_compiled_info);
     g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
 
-    /* Get the compile-time version information string */
-    // XXX qtshark
-    comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
-                                              get_gui_compiled_info);
-
-    /* Assemble the run-time version information string */
-    // xxx qtshark
-    runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
-
-    /*
-     * In order to have the -X opts assigned before the wslua machine starts
-     * we need to call getopt_long before epan_init() gets called.
-     *
-     * In addition, we process "console only" parameters (ones where we
-     * send output to the console and exit) here, so we don't start Qt
-     * if we're only showing command-line help or version information.
-     *
-     * XXX - this pre-scan is done before we start Qt, so we haven't
-     * run WiresharkApplication's constructor on the arguments.  That
-     * means that Qt arguments have not been removed from the argument
-     * list; those arguments begin with "-", and may be treated as
-     * errors by getopt_long().
-     *
-     * We thus ignore errors - *and* set "opterr" to 0 to suppress the
-     * error messages.
-     *
-     * XXX - is there some way to parse and remove Qt arguments without
-     * starting up the GUI, which we can call before calling this?
-     *
-     * In order to handle, for example, -o options, we also need to call it
-     * *after* epan_init() gets called, so that the dissectors have had a
-     * chance to register their preferences, so we have another getopt_long()
-     * call later.
-     *
-     * XXX - can we do this all with one getopt_long() call, saving the
-     * arguments we can't handle until after initializing libwireshark,
-     * and then process them after initializing libwireshark?
-     *
-     * Note that we don't want to initialize libwireshark until after the
-     * GUI is up, as that can take a while, and we want a window of some
-     * sort up to show progress while that's happening.
-     */
-    // XXX Should the remaining code be in WiresharkApplcation::WiresharkApplication?
-#define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:g:Hh" "jJ:kK:lm:nN:o:P:r:R:St:u:vw:X:Y:z:"
-DIAG_OFF(cast-qual)
-    static const struct option long_options[] = {
-        {(char *)"help", no_argument, NULL, 'h'},
-        {(char *)"read-file", required_argument, NULL, 'r' },
-        {(char *)"read-filter", required_argument, NULL, 'R' },
-        {(char *)"display-filter", required_argument, NULL, 'Y' },
-        {(char *)"version", no_argument, NULL, 'v'},
-        LONGOPT_CAPTURE_COMMON
-        {0, 0, 0, 0 }
-    };
-DIAG_ON(cast-qual)
-    static const char optstring[] = OPTSTRING;
-
-    opterr = 0;
-
-    while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
-        switch (opt) {
-            case 'C':        /* Configuration Profile */
-                if (profile_exists (optarg, FALSE)) {
-                    set_profile_name (optarg);
-                } else {
-                    cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
-                    exit(1);
-                }
-                break;
-            case 'D':        /* Print a list of capture devices and exit */
-#ifdef HAVE_LIBPCAP
-                if_list = capture_interface_list(&err, &err_str, NULL);
-                if (if_list == NULL) {
-                    if (err == 0)
-                        cmdarg_err("There are no interfaces on which a capture can be done");
-                    else {
-                        cmdarg_err("%s", err_str);
-                        g_free(err_str);
-                    }
-                    exit(2);
-                }
-#ifdef _WIN32
-                create_console();
-#endif /* _WIN32 */
-                capture_opts_print_interfaces(if_list);
-                free_interface_list(if_list);
-#ifdef _WIN32
-                destroy_console();
-#endif /* _WIN32 */
-                exit(0);
-#else /* HAVE_LIBPCAP */
-                capture_option_specified = TRUE;
-                arg_error = TRUE;
-#endif /* HAVE_LIBPCAP */
-                break;
-            case 'h':        /* Print help and exit */
-                print_usage(TRUE);
-                exit(0);
-                break;
-#ifdef _WIN32
-            case 'i':
-                if (strcmp(optarg, "-") == 0)
-                    set_stdin_capture(TRUE);
-                break;
-#endif
-            case 'P':        /* Personal file directory path settings - change these before the Preferences and alike are processed */
-                if (!persfilepath_opt(opt, optarg)) {
-                    cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
-                    exit(2);
-                }
-                break;
-            case 'v':        /* Show version and exit */
-#ifdef _WIN32
-                create_console();
-#endif
-                show_version("Wireshark", comp_info_str, runtime_info_str);
-#ifdef _WIN32
-                destroy_console();
-#endif
-                exit(0);
-                break;
-            case 'X':
-                /*
-                 *  Extension command line options have to be processed before
-                 *  we call epan_init() as they are supposed to be used by dissectors
-                 *  or taps very early in the registration process.
-                 */
-                ex_opt_add(optarg);
-                break;
-            case '?':        /* Ignore errors - the "real" scan will catch them. */
-                break;
-        }
-    }
-
-#ifdef _WIN32
-    reset_library_path();
-#endif
-
-    /* Create The Wireshark app */
-    WiresharkApplication ws_app(argc, argv);
-
-    /* initialize the funnel mini-api */
-    // xxx qtshark
-    //initialize_funnel_ops();
-
-    AirPDcapInitContext(&airpdcap_ctx);
-
-// xxx qtshark
 #ifdef _WIN32
+    ws_init_dll_search_path();
     /* Load wpcap if possible. Do this before collecting the run-time version information */
     load_wpcap();
 
@@ -644,14 +420,16 @@ DIAG_ON(cast-qual)
 #ifdef HAVE_AIRPCAP
     /* Load the airpcap.dll.  This must also be done before collecting
      * run-time version information. */
+    load_airpcap();
+#if 0
     airpcap_dll_ret_val = load_airpcap();
 
     switch (airpcap_dll_ret_val) {
     case AIRPCAP_DLL_OK:
         /* load the airpcap interfaces */
-        airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
+        g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
 
-        if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
+        if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
             if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
                 g_free(err_str);
@@ -664,7 +442,6 @@ DIAG_ON(cast-qual)
             airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
         }
         break;
-#if 0
     /*
      * XXX - Maybe we need to warn the user if one of the following happens???
      */
@@ -679,25 +456,47 @@ DIAG_ON(cast-qual)
     case AIRPCAP_DLL_NOT_FOUND:
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
         break;
-#endif
     }
+#endif
 #endif /* HAVE_AIRPCAP */
 #endif /* _WIN32 */
 
-    QString locale;
-    QString cf_name;
-    unsigned int in_file_type = WTAP_TYPE_AUTO;
+    /* Get the compile-time version information string */
+    comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
+                                              get_gui_compiled_info);
 
-    // In Qt 5, C strings are treated always as UTF-8 when converted to
-    // QStrings; in Qt 4, the codec must be set to make that happen
-#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
-    // Hopefully we won't have to use QString::fromUtf8() in as many places.
-    QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
-    QTextCodec::setCodecForCStrings(utf8codec);
-    // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
-    QTextCodec::setCodecForTr(utf8codec);
+    /* Assemble the run-time version information string */
+    runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
+
+    profile_store_persconffiles(TRUE);
+
+    /* Read the profile independent recent file.  We have to do this here so we can */
+    /* set the profile before it can be set from the command line parameter */
+    if (!recent_read_static(&rf_path, &rf_open_errno)) {
+        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+                      "Could not open common recent file\n\"%s\": %s.",
+                      rf_path, strerror(rf_open_errno));
+        g_free(rf_path);
+    }
+
+    commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
+
+#ifdef _WIN32
+    reset_library_path();
 #endif
 
+    /* Create The Wireshark app */
+    WiresharkApplication ws_app(argc, qt_argv);
+
+    /* initialize the funnel mini-api */
+    // xxx qtshark
+    //initialize_funnel_ops();
+
+    AirPDcapInitContext(&airpdcap_ctx);
+
+    QString cf_name;
+    unsigned int in_file_type = WTAP_TYPE_AUTO;
+
     /* Add it to the information to be reported on a crash. */
     ws_add_crash_info("Wireshark %s\n"
            "\n"
@@ -705,68 +504,44 @@ DIAG_ON(cast-qual)
            "\n"
            "%s",
         get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
+    g_string_free(comp_info_str, TRUE);
+    g_string_free(runtime_info_str, TRUE);
 
 #ifdef _WIN32
     /* Start windows sockets */
     WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
 #endif  /* _WIN32 */
 
-    profile_store_persconffiles(TRUE);
-
-    /* Read the profile independent recent file.  We have to do this here so we can */
-    /* set the profile before it can be set from the command line parameter */
-    recent_read_static(&rf_path, &rf_open_errno);
-    if (rf_path != NULL && rf_open_errno != 0) {
-        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                      "Could not open common recent file\n\"%s\": %s.",
-                      rf_path, strerror(rf_open_errno));
-    }
-    wsApp->emitAppSignal(WiresharkApplication::StaticRecentFilesRead);
-
-    /* Init the "Open file" dialog directory */
-    /* (do this after the path settings are processed) */
-
     /* Read the profile dependent (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_profile_static(&rf_path, &rf_open_errno);
-    if (rf_path != NULL && rf_open_errno != 0) {
+    if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
                       "Could not open recent file\n\"%s\": %s.",
                       rf_path, g_strerror(rf_open_errno));
+        g_free(rf_path);
     }
+    wsApp->applyCustomColorsFromRecent();
 
     // Initialize our language
     read_language_prefs();
-    locale = QString(language);
-    wsApp->loadLanguage(locale);
+    wsApp->loadLanguage(language);
 
-    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
 
     // Init the main window (and splash)
     main_w = new(MainWindow);
     main_w->show();
     // We may not need a queued connection here but it would seem to make sense
     // to force the issue.
-    main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString&,QString&,unsigned int)),
-            main_w, SLOT(openCaptureFile(QString&,QString&,unsigned int)));
+    main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
+            main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
+    main_w->connect(&ws_app, SIGNAL(openCaptureOptions()),
+            main_w, SLOT(on_actionCaptureOptions_triggered()));
 
     /* Init the "Open file" dialog directory */
     /* (do this after the path settings are processed) */
-
-    /* Read the profile dependent (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_profile_static(&rf_path, &rf_open_errno);
-    if (rf_path != NULL && rf_open_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-            "Could not open recent file\n\"%s\": %s.",
-            rf_path, g_strerror(rf_open_errno));
-    }
-    wsApp->emitAppSignal(WiresharkApplication::StaticRecentFilesRead);
-
     if (recent.gui_fileopen_remembered_dir &&
         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
@@ -780,6 +555,9 @@ DIAG_ON(cast-qual)
 #endif
 
     set_console_log_handler();
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "set_console_log_handler, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
 
 #ifdef HAVE_LIBPCAP
     /* Set the initial values in the capture options. This might be overwritten
@@ -787,45 +565,68 @@ DIAG_ON(cast-qual)
     capture_opts_init(&global_capture_opts);
 #endif
 
-    init_report_err(failure_alert_box, open_failure_alert_box,
+    init_report_err(vfailure_alert_box, open_failure_alert_box,
                     read_failure_alert_box, write_failure_alert_box);
 
-    init_open_routines();
+    wtap_init();
 
 #ifdef HAVE_PLUGINS
     /* Register all the plugin types we have. */
     epan_register_plugin_types(); /* Types known to libwireshark */
-    wtap_register_plugin_types(); /* Types known to libwiretap */
-    codec_register_plugin_types(); /* Types known to libcodec */
+    codec_register_plugin_types(); /* Types known to libwscodecs */
 
     /* Scan for plugins.  This does *not* call their registration routines;
        that's done later. */
-    scan_plugins();
+    scan_plugins(REPORT_LOAD_FAILURE);
 
     /* Register all libwiretap plugin modules. */
     register_all_wiretap_modules();
+#endif
 
     /* Register all audio codec plugins. */
     register_all_codecs();
-#endif
 
+    splash_update(RA_DISSECTORS, NULL, NULL);
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling epan init, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
     /* Register all dissectors; we must do this before checking for the
        "-G" flag, as the "-G" flag dumps information registered by the
        dissectors, and we must do it before we read the preferences, in
        case any dissectors register preferences. */
-    epan_init(register_all_protocols,register_all_protocol_handoffs,
-              splash_update, NULL);
+    if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
+                   splash_update, NULL)) {
+        SimpleDialog::displayQueuedMessages(main_w);
+        ret_val = INIT_FAILED;
+        goto clean_exit;
+    }
+#ifdef DEBUG_STARTUP_TIME
+    /* epan_init resets the preferences */
+    prefs.console_log_level = DEBUG_STARTUP_TIME_LOGLEVEL;
+    prefs.gui_console_open = console_open_always;
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "epan done, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
 
-    splash_update(RA_LISTENERS, NULL, NULL);
+    // Read the dynamic part of the recent file. This determines whether or
+    // not the recent list appears in the main window so the earlier we can
+    // call this the better.
+    if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
+        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+                      "Could not open recent file\n\"%s\": %s.",
+                      rf_path, g_strerror(rf_open_errno));
+        g_free(rf_path);
+    }
 
+    splash_update(RA_LISTENERS, NULL, NULL);
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Register all tap listeners, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
     /* Register all tap listeners; we do this before we parse the arguments,
        as the "-z" argument can specify a registered tap. */
 
     /* we register the plugin taps before the other taps because
             stats_tree taps plugins will be registered as tap listeners
             by stats_tree_stat.c and need to registered before that */
-
-    g_log(NULL, G_LOG_LEVEL_DEBUG, "plugin_dir: %s", get_plugin_dir());
 #ifdef HAVE_PLUGINS
     register_all_plugin_tap_listeners();
 #endif
@@ -833,382 +634,65 @@ DIAG_ON(cast-qual)
     register_all_tap_listeners();
     conversation_table_set_gui_info(init_conversation_table);
     hostlist_table_set_gui_info(init_endpoint_table);
+    srt_table_iterate_tables(register_service_response_tables, NULL);
+    rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
+    new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
 
     if (ex_opt_count("read_format") > 0) {
         in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
     }
 
-    splash_update(RA_PREFERENCES, NULL, NULL);
-
-    prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path);
-
-    /*
-     * To reset the options parser, set optreset to 1 on platforms that
-     * have optreset (documented in *BSD and OS X, apparently present but
-     * not documented in Solaris - the Illumos repository seems to
-     * suggest that the first Solaris getopt_long(), at least as of 2004,
-     * was based on the NetBSD one, it had optreset) and set optind to 1,
-     * and set optind to 0 otherwise (documented as working in the GNU
-     * getopt_long().  Setting optind to 0 didn't originally work in the
-     * NetBSD one, but that was added later - we don't want to depend on
-     * it if we have optreset).
-     *
-     * Also reset opterr to 1, so that error messages are printed by
-     * getopt_long().
-     *
-     * 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.  But we're now using getopt_long() - what does it do?
-     */
-#ifdef HAVE_OPTRESET
-    optreset = 1;
-    optind = 1;
-#else
-    optind = 0;
-#endif
-    opterr = 1;
-
-    /* Now get our args */
-    while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
-        switch (opt) {
-        /*** capture option specific ***/
-        case 'a':        /* autostop criteria */
-        case 'b':        /* Ringbuffer option */
-        case 'c':        /* Capture xxx packets */
-        case 'f':        /* capture filter */
-        case 'k':        /* Start capture immediately */
-        case 'H':        /* Hide capture info dialog box */
-        case 'p':        /* Don't capture in promiscuous mode */
-        case 'i':        /* Use interface x */
-#ifdef HAVE_PCAP_CREATE
-        case 'I':        /* Capture in monitor mode, if available */
-#endif
-#ifdef HAVE_PCAP_REMOTE
-        case 'A':        /* Authentication */
-#endif
-        case 's':        /* Set the snapshot (capture) length */
-        case 'S':        /* "Sync" mode: used for following file ala tail -f */
-        case 'w':        /* Write to capture file xxx */
-        case 'y':        /* Set the pcap data link type */
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        case 'B':        /* Buffer size */
-#endif /* _WIN32 or HAVE_PCAP_CREATE */
-#ifdef HAVE_LIBPCAP
-            status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
-                                          &start_capture);
-            if(status != 0) {
-                exit(status);
-            }
-#else
-            capture_option_specified = TRUE;
-            arg_error = TRUE;
+#ifdef HAVE_EXTCAP
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
 #endif
-            break;
-#ifdef HAVE_KERBEROS
-        case 'K':        /* Kerberos keytab file */
-            read_keytab_file(optarg);
-            break;
+    splash_update(RA_EXTCAP, NULL, NULL);
+    extcap_register_preferences();
 #endif
+    splash_update(RA_PREFERENCES, NULL, NULL);
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling module preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
 
-        /*** all non capture option specific ***/
-        case 'C':
-            /* Configuration profile settings were already processed just ignore them this time*/
-            break;
-        case 'j':        /* Search backwards for a matching packet from filter in option J */
-            /* Not supported yet */
-            break;
-        case 'g':        /* Go to packet with the given packet number */
-            go_to_packet = get_positive_int(optarg, "go to packet");
-            break;
-        case 'J':        /* Jump to the first packet which matches the filter criteria */
-            /* Not supported yet */
-            break;
-        case 'l':        /* Automatic scrolling in live capture mode */
-#ifdef HAVE_LIBPCAP
-            /* Not supported yet */
-#else
-            capture_option_specified = TRUE;
-            arg_error = TRUE;
-#endif
-            break;
-        case 'L':        /* Print list of link-layer types and exit */
-#ifdef HAVE_LIBPCAP
-                list_link_layer_types = TRUE;
-#else
-                capture_option_specified = TRUE;
-                arg_error = TRUE;
-#endif
-            break;
-        case 'm':        /* Fixed-width font for the display */
-            /* Not supported yet */
-            break;
-        case 'n':        /* No name resolution */
-            gbl_resolv_flags.mac_name = FALSE;
-            gbl_resolv_flags.network_name = FALSE;
-            gbl_resolv_flags.transport_name = FALSE;
-            gbl_resolv_flags.concurrent_dns = FALSE;
-            break;
-        case 'N':        /* Select what types of addresses/port #s to resolve */
-            badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
-            if (badopt != '\0') {
-                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_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:
-                    cmdarg_err("-o flag \"%s\" specifies obsolete preference",
-                               optarg);
-                    exit(1);
-                    break;
-                default:
-                    g_assert_not_reached();
-            }
-            break;
-        case 'P':
-            /* Path settings were already processed just ignore them this time*/
-            break;
-        case 'r':
-            cf_name = optarg;
-            break;
-        case 'R':        /* Read file filter */
-            read_filter = QString(optarg);
-            break;
-        case 't':        /* Time stamp type */
-            if (strcmp(optarg, "r") == 0)
-                timestamp_set_type(TS_RELATIVE);
-            else if (strcmp(optarg, "a") == 0)
-                timestamp_set_type(TS_ABSOLUTE);
-            else if (strcmp(optarg, "ad") == 0)
-                timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
-            else if (strcmp(optarg, "adoy") == 0)
-                timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
-            else if (strcmp(optarg, "d") == 0)
-                timestamp_set_type(TS_DELTA);
-            else if (strcmp(optarg, "dd") == 0)
-                timestamp_set_type(TS_DELTA_DIS);
-            else if (strcmp(optarg, "e") == 0)
-                timestamp_set_type(TS_EPOCH);
-            else if (strcmp(optarg, "u") == 0)
-                timestamp_set_type(TS_UTC);
-            else if (strcmp(optarg, "ud") == 0)
-                timestamp_set_type(TS_UTC_WITH_YMD);
-            else if (strcmp(optarg, "udoy") == 0)
-                timestamp_set_type(TS_UTC_WITH_YDOY);
-            else {
-                cmdarg_err("Invalid time stamp type \"%s\"", optarg);
-                cmdarg_err_cont(
-"It must be \"a\" for absolute, \"ad\" for absolute with YYYY-MM-DD date,");
-                cmdarg_err_cont(
-"\"adoy\" for absolute with YYYY/DOY date, \"d\" for delta,");
-                cmdarg_err_cont(
-"\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative,");
-                cmdarg_err_cont(
-"\"u\" for absolute UTC, \"ud\" for absolute UTC with YYYY-MM-DD date,");
-                cmdarg_err_cont(
-"or \"udoy\" for absolute UTC with YYYY/DOY date.");
-                exit(1);
-            }
-            break;
-        case 'u':        /* Seconds type */
-            if (strcmp(optarg, "s") == 0)
-                timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
-            else if (strcmp(optarg, "hms") == 0)
-                timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
-            else {
-                cmdarg_err("Invalid seconds type \"%s\"", optarg);
-                cmdarg_err_cont(
-"It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
-                exit(1);
-            }
-            break;
-        case 'X':
-            /* ext ops were already processed just ignore them this time*/
-            break;
-        case 'Y':
-            dfilter = QString(optarg);
-            break;
-        case 'z':
-            /* 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 stat arguments. */
-            if (strcmp("help", optarg) == 0) {
-              fprintf(stderr, "wireshark: The available statistics for the \"-z\" option are:\n");
-              list_stat_cmd_args();
-              exit(0);
-            }
-            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;
-        default:
-        case '?':        /* Bad flag - print usage message */
-            print_usage(FALSE);
-            exit(0);
-            break;
-        }
-    }
-
-    if (!arg_error) {
-        argc -= optind;
-        argv += optind;
-        if (argc >= 1) {
-            if (!cf_name.isEmpty()) {
-                /*
-                 * 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 {
-                /*
-                 * Input file name not specified with "-r", and a command-line argument
-                 * was specified; treat it as the input file name.
-                 *
-                 * Yes, this is different from tshark, where non-flag command-line
-                 * arguments are a filter, but this works better on GUI desktops
-                 * where a command can be specified to be run to open a particular
-                 * file - yes, you could have "-r" as the last part of the command,
-                 * but that's a bit ugly.
-                 */
-                cf_name = argv[0];
+    global_commandline_info.prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
 
-            }
-            argc--;
-            argv++;
-        }
+    /* Now get our args */
+    commandline_other_options(argc, argv, TRUE);
 
-        if (argc != 0) {
-            /*
-             * Extra command line arguments were specified; complain.
-             */
-            cmdarg_err("Invalid argument: %s", argv[0]);
-            arg_error = TRUE;
-        }
-    }
-    if (arg_error) {
-#ifndef HAVE_LIBPCAP
-        if (capture_option_specified) {
-            cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
-        }
-#endif
-        print_usage(FALSE);
-        exit(1);
-    }
+    /* Convert some command-line parameters to QStrings */
+    if (global_commandline_info.cf_name != NULL)
+        cf_name = QString(global_commandline_info.cf_name);
+    if (global_commandline_info.rfilter != NULL)
+        read_filter = QString(global_commandline_info.rfilter);
+    if (global_commandline_info.dfilter != NULL)
+        dfilter = QString(global_commandline_info.dfilter);
 
     /* Removed thread code:
      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
      */
 
-    // XXX Is there a better place to set the timestamp format & precision?
     timestamp_set_type(recent.gui_time_format);
     timestamp_set_precision(recent.gui_time_precision);
-    timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
+    timestamp_set_seconds_type (recent.gui_seconds_format);
 
 #ifdef HAVE_LIBPCAP
-    fill_in_local_interfaces(main_window_update);
-
-    if (start_capture && list_link_layer_types) {
-        /* Specifying *both* is bogus. */
-        cmdarg_err("You can't specify both -L and a live capture.");
-        exit(1);
-    }
-
-    if (list_link_layer_types) {
-        /* We're supposed to list the link-layer types for an interface;
-           did the user also specify a capture file to be read? */
-        if (!cf_name.isEmpty()) {
-            /* Yes - that's bogus. */
-            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 (global_capture_opts.multi_files_on) {
-            cmdarg_err("Ring buffer requested, but a capture isn't being done.");
-            exit(1);
-        }
-    } else {
-        /* We're supposed to do a live capture; did the user also specify
-           a capture file to be read? */
-        if (start_capture && !cf_name.isEmpty()) {
-            /* Yes - that's bogus. */
-            cmdarg_err("You can't specify both a live capture and a capture file to be read.");
-            exit(1);
-        }
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling fill_in_local_interfaces, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
+    splash_update(RA_INTERFACES, NULL, NULL);
 
-        /* No - was the ring buffer option specified and, if so, does it make
-           sense? */
-        if (global_capture_opts.multi_files_on) {
-            /* Ring buffer works only under certain conditions:
-             a) ring buffer does not work with temporary files;
-             b) real_time_mode and multi_files_on are mutually exclusive -
-             real_time_mode takes precedence;
-             c) it makes no sense to enable the ring buffer if the maximum
-             file size is set to "infinite". */
-            if (global_capture_opts.save_file == NULL) {
-                cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
-                global_capture_opts.multi_files_on = FALSE;
-            }
-            if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
-                cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
-                /* XXX - this must be redesigned as the conditions changed */
-            }
-        }
-    }
+    fill_in_local_interfaces(main_window_update);
 
-    if (start_capture || list_link_layer_types) {
+    if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
         /* We're supposed to do a live capture or get a list of link-layer
            types for a live capture device; if the user didn't specify an
            interface to use, pick a default. */
-        status = capture_opts_default_iface_if_necessary(&global_capture_opts,
-        ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
-        if (status != 0) {
-            exit(status);
+        ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
+        ((global_commandline_info.prefs_p->capture_device) && (*global_commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(global_commandline_info.prefs_p->capture_device) : NULL);
+        if (ret_val != 0) {
+            goto clean_exit;
         }
     }
 
-    if (list_link_layer_types) {
+    if (global_commandline_info.list_link_layer_types) {
         /* Get the list of link-layer types for the capture devices. */
         if_capabilities_t *caps;
         guint i;
@@ -1218,18 +702,20 @@ DIAG_ON(cast-qual)
             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
             if (device.selected) {
 #if defined(HAVE_PCAP_CREATE)
-                caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str, main_window_update);
+                caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
 #else
-                caps = capture_get_if_capabilities(device.name, FALSE, &err_str,main_window_update);
+                caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
 #endif
                 if (caps == NULL) {
                     cmdarg_err("%s", err_str);
                     g_free(err_str);
-                    exit(2);
+                    ret_val = INVALID_CAPABILITY;
+                    goto clean_exit;
                 }
             if (caps->data_link_types == NULL) {
                 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
-                exit(2);
+                ret_val = INVALID_LINK_TYPE;
+                goto clean_exit;
             }
 #ifdef _WIN32
             create_console();
@@ -1245,16 +731,21 @@ DIAG_ON(cast-qual)
             free_if_capabilities(caps);
             }
         }
-        exit(0);
+        ret_val = EXIT_SUCCESS;
+        goto clean_exit;
     }
 
     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
     capture_opts_trim_ring_num_files(&global_capture_opts);
 #endif /* HAVE_LIBPCAP */
 
+
     /* Notify all registered modules that have had any of their preferences
        changed either from one of the preferences file or from the command
        line that their preferences have changed. */
+#ifdef DEBUG_STARTUP_TIME
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Calling prefs_apply_all, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
+#endif
     prefs_apply_all();
     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
 
@@ -1279,80 +770,127 @@ DIAG_ON(cast-qual)
     /* disabled protocols as per configuration file */
     if (gdp_path == NULL && dp_path == NULL) {
         set_disabled_protos_list();
+        set_enabled_protos_list();
+        set_disabled_heur_dissector_list();
+    }
+
+    if(global_dissect_options.disable_protocol_slist) {
+        GSList *proto_disable;
+        for (proto_disable = global_dissect_options.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
+        {
+            proto_disable_proto_by_name((char*)proto_disable->data);
+        }
+    }
+
+    if(global_dissect_options.enable_protocol_slist) {
+        GSList *proto_enable;
+        for (proto_enable = global_dissect_options.enable_protocol_slist; proto_enable != NULL; proto_enable = g_slist_next(proto_enable))
+        {
+            proto_enable_proto_by_name((char*)proto_enable->data);
+        }
+    }
+
+    if(global_dissect_options.enable_heur_slist) {
+        GSList *heur_enable;
+        for (heur_enable = global_dissect_options.enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
+        {
+            proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
+        }
+    }
+
+    if(global_dissect_options.disable_heur_slist) {
+        GSList *heur_disable;
+        for (heur_disable = global_dissect_options.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
+        {
+            proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
+        }
     }
 
-    build_column_format_array(&CaptureFile::globalCapFile()->cinfo, prefs_p->num_cols, TRUE);
+    build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
+    wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
+    wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
 
     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
 
+    /* For update of WindowTitle (When use gui.window_title preference) */
+    main_w->setWSWindowTitle();
 ////////
 
-    /* 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);
-    if (rf_path != NULL && rf_open_errno != 0) {
-        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                      "Could not open recent file\n\"%s\": %s.",
-                      rf_path, g_strerror(rf_open_errno));
-    }
-
-    color_filters_enable(recent.packet_list_colorize);
+    packet_list_enable_color(recent.packet_list_colorize);
 
     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
-    color_filters_enable(TRUE);
+    packet_list_enable_color(TRUE);
 
 ////////
 
 
 ////////
-    color_filters_init();
+    if (!color_filters_init(&err_msg, color_filter_add_cb)) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
+        g_free(err_msg);
+    }
 
 ////////
 
 #ifdef HAVE_LIBPCAP
     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
-    if (!start_capture && !global_capture_opts.default_options.cfilter) {
+    if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
         global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
     }
 #else /* HAVE_LIBPCAP */
     ////////
 #endif /* HAVE_LIBPCAP */
 
-//    w->setEnabled(true);
     wsApp->allSystemsGo();
-    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go, elapsed time %" G_GUINT64_FORMAT "us \n", g_get_monotonic_time() - start_time);
     SimpleDialog::displayQueuedMessages(main_w);
 
-    /* user could specify filename, or display filter, or both */
+    /* User could specify filename, or display filter, or both */
+    if (!dfilter.isEmpty())
+        main_w->filterPackets(dfilter, false);
     if (!cf_name.isEmpty()) {
-
-        /* Open stat windows; we do so after creating the main window,
-           to avoid Qt warnings, and after successfully 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();
-
-        // XXX The GTK+ UI does error checking here.
-        main_w->openCaptureFile(cf_name, read_filter, in_file_type);
-        if (!dfilter.isEmpty())
-            main_w->filterPackets(dfilter, false);
-        if(go_to_packet != 0) {
-            /* Jump to the specified frame number, kept for backward
-               compatibility. */
-            cf_goto_frame(CaptureFile::globalCapFile(), go_to_packet);
+        if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
+
+            /* Open stat windows; we do so after creating the main window,
+               to avoid Qt warnings, and after successfully 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();
+
+            if(global_commandline_info.go_to_packet != 0) {
+                /* Jump to the specified frame number, kept for backward
+                   compatibility. */
+                cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
+            } else if (global_commandline_info.jfilter != NULL) {
+                dfilter_t *jump_to_filter = NULL;
+                /* try to compile given filter */
+                if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
+                    // Similar code in MainWindow::mergeCaptureFile().
+                    QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
+                                         QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
+                                                 .arg(global_commandline_info.jfilter, err_msg),
+                                         QMessageBox::Ok);
+                    g_free(err_msg);
+                } else {
+                    /* Filter ok, jump to the first packet matching the filter
+                       conditions. Default search direction is forward, but if
+                       option d was given, search backwards */
+                    cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
+                }
+            }
         }
     }
 #ifdef HAVE_LIBPCAP
     else {
-        if (start_capture) {
+        if (global_commandline_info.start_capture) {
             if (global_capture_opts.save_file != NULL) {
                 /* Save the directory name for future file dialogs. */
                 /* (get_dirname overwrites filename) */
-                gchar *s = get_dirname(g_strdup(global_capture_opts.save_file));
-                set_last_open_dir(s);
+                gchar *s = g_strdup(global_capture_opts.save_file);
+                set_last_open_dir(get_dirname(s));
                 g_free(s);
             }
             /* "-k" was specified; start a capture. */
@@ -1365,7 +903,7 @@ DIAG_ON(cast-qual)
             if (global_capture_opts.ifaces->len == 0)
                 collect_ifaces(&global_capture_opts);
             CaptureFile::globalCapFile()->window = main_w;
-            if (capture_start(&global_capture_opts, main_w->captureSession(), main_window_update)) {
+            if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
                 /* 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 compute
@@ -1376,14 +914,45 @@ DIAG_ON(cast-qual)
             }
         }
     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
-        if (!start_capture && !global_capture_opts.default_options.cfilter) {
+        if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
         }
     }
 #endif /* HAVE_LIBPCAP */
 
-    g_main_loop_new(NULL, FALSE);
-    return wsApp->exec();
+    profile_store_persconffiles(FALSE);
+
+    ret_val = wsApp->exec();
+
+    epan_cleanup();
+
+#ifdef HAVE_EXTCAP
+    extcap_cleanup();
+#endif
+
+    AirPDcapDestroyContext(&airpdcap_ctx);
+
+#ifdef _WIN32
+    /* Shutdown windows sockets */
+    WSACleanup();
+
+    /* For some unknown reason, the "atexit()" call in "create_console()"
+       doesn't arrange that "destroy_console()" be called when we exit,
+       so we call it here if a console was created. */
+    destroy_console();
+#endif /* _WIN32 */
+
+clean_exit:
+#ifdef HAVE_LIBPCAP
+    capture_opts_cleanup(&global_capture_opts);
+#endif
+    col_cleanup(&CaptureFile::globalCapFile()->cinfo);
+    wtap_cleanup();
+    free_progdirs();
+#ifdef HAVE_PLUGINS
+    plugins_cleanup();
+#endif
+    return ret_val;
 }
 
 /*