#include "wsutil/wsgetopt.h"
#endif
+#ifndef _WIN32
+#include <wsutil/glib-compat.h>
+#endif
+
#include <wsutil/clopts_common.h>
#include <wsutil/cmdarg_err.h>
#include <wsutil/crash_info.h>
#ifdef HAVE_PLUGINS
#include <wsutil/plugins.h>
#endif
-#include <wsutil/report_err.h>
+#include <wsutil/report_message.h>
#include <wsutil/unicode-utils.h>
#include <ws_version_info.h>
#include <epan/dissectors/packet-kerberos.h>
#endif
-#ifdef HAVE_PLUGINS
#include <codecs/codecs.h>
-#endif
#ifdef HAVE_EXTCAP
#include <extcap.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/conversation_dialog.h"
#include "ui/qt/color_utils.h"
#include <QTextCodec>
#endif
-#if defined(HAVE_LIBPCAP) || defined(HAVE_EXTCAP)
-capture_options global_capture_opts;
-#endif
+#define INVALID_OPTION 1
+#define INIT_FAILED 2
+#define INVALID_CAPABILITY 2
+#define INVALID_LINK_TYPE 2
+
+//#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)
#else
g_string_append(str, "without AirPcap");
#endif
+
+ codec_get_compiled_version_info(str);
}
// xxx copied from ../gtk/main.c
#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;
#endif
- int ret_val;
- char **ws_argv = argv;
+ int ret_val = EXIT_SUCCESS;
+ char **argv = qt_argv;
#ifdef _WIN32
+ int result;
WSADATA wsaData;
#endif /* _WIN32 */
char *rf_path;
int rf_open_errno;
- char *gdp_path, *dp_path;
#ifdef HAVE_LIBPCAP
gchar *err_str;
- int status;
#else
#ifdef _WIN32
#ifdef HAVE_AIRPCAP
#endif
#endif
#endif
+ gchar *err_msg = NULL;
GString *comp_info_str = NULL;
GString *runtime_info_str = NULL;
- commandline_param_info_t commandline_info;
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
#ifdef _WIN32
// QCoreApplication clobbers argv. Let's have a local copy.
- ws_argv = (char **) g_malloc(sizeof(char *) * argc);
+ argv = (char **) g_malloc(sizeof(char *) * argc);
for (opt = 0; opt < argc; opt++) {
- ws_argv[opt] = argv[opt];
+ argv[opt] = qt_argv[opt];
}
- arg_list_utf_16to8(argc, ws_argv);
+ arg_list_utf_16to8(argc, argv);
create_app_running_mutex();
#endif /* _WIN32 */
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(ws_argv[0],
+ /* init_progfile_dir_error = */ init_progfile_dir(argv[0],
(int (*)(int, char **)) get_gui_compiled_info);
g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
/* Assemble the run-time version information string */
runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
+ /* Create the user profiles directory */
+ if (create_profiles_dir(&rf_path) == -1) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not create profiles directory\n\"%s\"",
+ rf_path);
+ g_free (rf_path);
+ }
+
profile_store_persconffiles(TRUE);
/* Read the profile independent recent file. We have to do this here so we can */
g_free(rf_path);
}
- commandline_early_options(argc, ws_argv, comp_info_str, runtime_info_str);
+ 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, argv);
+ WiresharkApplication ws_app(argc, qt_argv);
/* initialize the funnel mini-api */
// xxx qtshark
"\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 );
+ result = WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
+ if (result != 0)
+ {
+ ret_val = INIT_FAILED;
+ goto clean_exit;
+ }
#endif /* _WIN32 */
/* Read the profile dependent (static part) of the recent file. */
// 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(openCaptureOptions()),
+ main_w, SLOT(on_actionCaptureOptions_triggered()));
/* Init the "Open file" dialog directory */
/* (do this after the path settings are processed) */
#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
capture_opts_init(&global_capture_opts);
#endif
- init_report_err(vfailure_alert_box, open_failure_alert_box,
- read_failure_alert_box, write_failure_alert_box);
+ init_report_message(vfailure_alert_box, vwarning_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 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
if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
splash_update, NULL)) {
SimpleDialog::displayQueuedMessages(main_w);
- return 2;
+ 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. */
register_all_plugin_tap_listeners();
#endif
-#ifdef HAVE_EXTCAP
- extcap_register_preferences();
-#endif
-
register_all_tap_listeners();
conversation_table_set_gui_info(init_conversation_table);
hostlist_table_set_gui_info(init_endpoint_table);
in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
}
+#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
+ 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);
- commandline_info.prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
+ global_commandline_info.prefs_p = ws_app.readConfigurationFiles(false);
/* Now get our args */
- commandline_other_options(argc, argv, &commandline_info, TRUE);
+ commandline_other_options(argc, argv, TRUE);
/* Convert some command-line parameters to QStrings */
- if (commandline_info.cf_name != NULL)
- cf_name = QString(commandline_info.cf_name);
- if (commandline_info.rfilter != NULL)
- read_filter = QString(commandline_info.rfilter);
- if (commandline_info.dfilter != NULL)
- dfilter = QString(commandline_info.dfilter);
+ 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 (recent.gui_seconds_format);
#ifdef HAVE_LIBPCAP
+#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);
+
fill_in_local_interfaces(main_window_update);
- if (commandline_info.start_capture || commandline_info.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,
- ((commandline_info.prefs_p->capture_device) && (*commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(commandline_info.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 (commandline_info.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;
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();
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);
}
#endif
- /* disabled protocols as per configuration file */
- if (gdp_path == NULL && dp_path == NULL) {
- set_disabled_protos_list();
- set_disabled_heur_dissector_list();
- }
-
- if(commandline_info.disable_protocol_slist) {
- GSList *proto_disable;
- for (proto_disable = commandline_info.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
- {
- proto_disable_proto_by_name((char*)proto_disable->data);
- }
- }
-
- if(commandline_info.enable_heur_slist) {
- GSList *heur_enable;
- for (heur_enable = commandline_info.enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
- {
- proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
- }
- }
-
- if(commandline_info.disable_heur_slist) {
- GSList *heur_disable;
- for (heur_disable = commandline_info.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
- {
- proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
- }
+ /*
+ * Enabled and disabled protocols and heuristic dissectors as per
+ * command-line options.
+ */
+ if (!setup_enabled_and_disabled_protocols()) {
+ ret_val = INVALID_OPTION;
+ goto clean_exit;
}
- build_column_format_array(&CaptureFile::globalCapFile()->cinfo, commandline_info.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::RecentFilesRead); // Must be emitted after PreferencesChanged.
+ wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged.
wsApp->setMonospaceFont(prefs.gui_qt_font_name);
main_w->setWSWindowTitle();
////////
- /* Read the dynamic part of the recent file, as we have the gui now ready for
- it. */
- 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);
- }
-
packet_list_enable_color(recent.packet_list_colorize);
g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
////////
- gchar* err_msg = NULL;
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 (!commandline_info.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 */
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 */
filter. */
start_requested_stats();
- if(commandline_info.go_to_packet != 0) {
+ if(global_commandline_info.go_to_packet != 0) {
/* Jump to the specified frame number, kept for backward
compatibility. */
- cf_goto_frame(CaptureFile::globalCapFile(), commandline_info.go_to_packet);
- } else if (commandline_info.jfilter != NULL) {
+ 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(commandline_info.jfilter, &jump_to_filter, &err_msg)) {
+ 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(commandline_info.jfilter, err_msg),
+ .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, commandline_info.jump_backwards);
+ cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
}
}
}
}
#ifdef HAVE_LIBPCAP
else {
- if (commandline_info.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) */
}
}
/* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
- if (!commandline_info.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 */
+ // UAT files used in configuration profiles which are used in Qt dialogs
+ // are not registered during startup because they only get loaded when
+ // the dialog is shown. Register them here.
+ g_free(get_persconffile_path("io_graphs", TRUE));
+
profile_store_persconffiles(FALSE);
ret_val = wsApp->exec();
epan_cleanup();
+#ifdef HAVE_EXTCAP
+ extcap_cleanup();
+#endif
+
AirPDcapDestroyContext(&airpdcap_ctx);
#ifdef _WIN32
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;
}