Put #ifdef/#endif around a variable used only on Windows.
[metze/wireshark/wip.git] / wireshark-qt.cpp
1 /* wireshark-qt.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <config.h>
23
24 #include <glib.h>
25
26 #ifdef Q_OS_UNIX
27 #include <signal.h>
28 #endif
29
30 #ifdef HAVE_GETOPT_H
31 #include <getopt.h>
32 #endif
33
34 #ifndef HAVE_GETOPT_LONG
35 #include "wsutil/wsgetopt.h"
36 #endif
37
38 #include <wsutil/clopts_common.h>
39 #include <wsutil/cmdarg_err.h>
40 #include <wsutil/crash_info.h>
41 #include <wsutil/filesystem.h>
42 #include <wsutil/privileges.h>
43 #ifdef HAVE_PLUGINS
44 #include <wsutil/plugins.h>
45 #endif
46 #include <wsutil/report_err.h>
47 #include <wsutil/unicode-utils.h>
48 #include <ws_version_info.h>
49
50 #include <epan/addr_resolv.h>
51 #include <epan/ex-opt.h>
52 #include <epan/tap.h>
53 #include <epan/stat_tap_ui.h>
54 #include <epan/column.h>
55 #include <epan/disabled_protos.h>
56 #include <epan/prefs.h>
57
58 #ifdef HAVE_KERBEROS
59 #include <epan/packet.h>
60 #include <epan/asn1.h>
61 #include <epan/dissectors/packet-kerberos.h>
62 #endif
63
64 #ifdef HAVE_PLUGINS
65 #include <codecs/codecs.h>
66 #endif
67
68 #ifdef HAVE_EXTCAP
69 #include <extcap.h>
70 #endif
71
72 /* general (not Qt specific) */
73 #include "file.h"
74 #include "epan/color_filters.h"
75 #include "log.h"
76
77 #include "epan/rtd_table.h"
78 #include "epan/srt_table.h"
79
80 #include "ui/alert_box.h"
81 #include "ui/console.h"
82 #include "ui/iface_lists.h"
83 #include "ui/language.h"
84 #include "ui/persfilepath_opt.h"
85 #include "ui/recent.h"
86 #include "ui/simple_dialog.h"
87 #include "ui/util.h"
88 #include "ui/commandline.h"
89
90 #include "ui/qt/conversation_dialog.h"
91 #include "ui/qt/color_utils.h"
92 #include "ui/qt/coloring_rules_dialog.h"
93 #include "ui/qt/endpoint_dialog.h"
94 #include "ui/qt/main_window.h"
95 #include "ui/qt/response_time_delay_dialog.h"
96 #include "ui/qt/service_response_time_dialog.h"
97 #include "ui/qt/simple_dialog.h"
98 #include "ui/qt/simple_statistics_dialog.h"
99 #include "ui/qt/splash_overlay.h"
100 #include "ui/qt/wireshark_application.h"
101
102 #include "caputils/capture-pcap-util.h"
103
104 #ifdef _WIN32
105 #  include "caputils/capture-wpcap.h"
106 #  include "caputils/capture_wpcap_packet.h"
107 #  include <tchar.h> /* Needed for Unicode */
108 #  include <wsutil/file_util.h>
109 #  include <wsutil/os_version_info.h>
110 #endif /* _WIN32 */
111
112 #ifdef HAVE_AIRPCAP
113 #  include <caputils/airpcap.h>
114 #  include <caputils/airpcap_loader.h>
115 //#  include "airpcap_dlg.h"
116 //#  include "airpcap_gui_utils.h"
117 #endif
118
119 #include "epan/crypt/airpdcap_ws.h"
120
121 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
122 #include <QTextCodec>
123 #endif
124
125 #if defined(HAVE_LIBPCAP) || defined(HAVE_EXTCAP)
126 capture_options global_capture_opts;
127 #endif
128
129 /* update the main window */
130 void main_window_update(void)
131 {
132     WiresharkApplication::processEvents();
133 }
134
135 #ifdef HAVE_LIBPCAP
136
137 /* quit a nested main window */
138 void main_window_nested_quit(void)
139 {
140 //    if (gtk_main_level() > 0)
141     wsApp->quit();
142 }
143
144 /* quit the main window */
145 void main_window_quit(void)
146 {
147     wsApp->quit();
148 }
149
150 #endif /* HAVE_LIBPCAP */
151
152 /*
153  * Report an error in command-line arguments.
154  * Creates a console on Windows.
155  */
156 // xxx copied from ../gtk/main.c
157 static void
158 wireshark_cmdarg_err(const char *fmt, va_list ap)
159 {
160 #ifdef _WIN32
161     create_console();
162 #endif
163     fprintf(stderr, "wireshark: ");
164     vfprintf(stderr, fmt, ap);
165     fprintf(stderr, "\n");
166 }
167
168 /*
169  * Report additional information for an error in command-line arguments.
170  * Creates a console on Windows.
171  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
172  * terminal isn't the standard error?
173  */
174 // xxx copied from ../gtk/main.c
175 static void
176 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
177 {
178 #ifdef _WIN32
179     create_console();
180 #endif
181     vfprintf(stderr, fmt, ap);
182     fprintf(stderr, "\n");
183 }
184
185 // xxx based from ../gtk/main.c:get_gtk_compiled_info
186 void
187 get_wireshark_qt_compiled_info(GString *str)
188 {
189     g_string_append(str, "with ");
190     g_string_append_printf(str,
191 #ifdef QT_VERSION
192                     "Qt %s", QT_VERSION_STR);
193 #else
194                     "Qt (version unknown)");
195 #endif
196
197     /* Capture libraries */
198     g_string_append(str, ", ");
199     get_compiled_caplibs_version(str);
200 }
201
202 // xxx copied from ../gtk/main.c
203 void
204 get_gui_compiled_info(GString *str)
205 {
206     epan_get_compiled_version_info(str);
207
208     g_string_append(str, ", ");
209 #ifdef QT_MULTIMEDIA_LIB
210     g_string_append(str, "with QtMultimedia");
211 #else
212     g_string_append(str, "without QtMultimedia");
213 #endif
214
215     g_string_append(str, ", ");
216 #ifdef HAVE_AIRPCAP
217     get_compiled_airpcap_version(str);
218 #else
219     g_string_append(str, "without AirPcap");
220 #endif
221 }
222
223 // xxx copied from ../gtk/main.c
224 void
225 get_wireshark_runtime_info(GString *str)
226 {
227 #ifdef HAVE_LIBPCAP
228     /* Capture libraries */
229     g_string_append(str, ", ");
230     get_runtime_caplibs_version(str);
231 #endif
232
233     /* stuff used by libwireshark */
234     epan_get_runtime_version_info(str);
235
236 #ifdef HAVE_AIRPCAP
237     g_string_append(str, ", ");
238     get_runtime_airpcap_version(str);
239 #endif
240 }
241
242 #ifdef HAVE_LIBPCAP
243 /*  Check if there's something important to tell the user during startup.
244  *  We want to do this *after* showing the main window so that any windows
245  *  we pop up will be above the main window.
246  */
247 static void
248 check_and_warn_user_startup(const QString &cf_name)
249 {
250 #ifndef _WIN32
251     Q_UNUSED(cf_name)
252 #endif
253     gchar               *cur_user, *cur_group;
254
255     /* Tell the user not to run as root. */
256     if (running_with_special_privs() && recent.privs_warn_if_elevated) {
257         cur_user = get_cur_username();
258         cur_group = get_cur_groupname();
259         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
260         "Running as user \"%s\" and group \"%s\".\n"
261         "This could be dangerous.\n\n"
262         "If you're running Wireshark this way in order to perform live capture, "
263         "you may want to be aware that there is a better way documented at\n"
264         "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
265         g_free(cur_user);
266         g_free(cur_group);
267     }
268
269 #ifdef _WIN32
270     /* Warn the user if npf.sys isn't loaded. */
271     if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
272         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
273         "The NPF driver isn't running. You may have trouble\n"
274         "capturing or listing interfaces.");
275     }
276 #endif
277
278 }
279 #endif
280
281 #ifdef _WIN32
282 // Try to avoid library search path collisions. QCoreApplication will
283 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
284 // the application directory. If
285 //
286 // - You have Qt version 5.x.y installed in the default location
287 //   (C:\Qt\5.x) on your machine.
288 //
289 // and
290 //
291 // - You install Wireshark that was built on a machine with Qt version
292 //   5.x.z installed in the default location.
293 //
294 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
295 // directory. This may not be compatible with qwindows.dll from that
296 // same path on the build machine. At any rate, loading DLLs from paths
297 // you don't control is ill-advised. We work around this by removing every
298 // path except our application directory.
299
300 static inline void
301 reset_library_path(void)
302 {
303     QString app_path = QDir(get_progfile_dir()).path();
304     foreach (QString path, QCoreApplication::libraryPaths()) {
305         QCoreApplication::removeLibraryPath(path);
306     }
307     QCoreApplication::addLibraryPath(app_path);
308 }
309 #endif
310
311 /* And now our feature presentation... [ fade to music ] */
312 int main(int argc, char *argv[])
313 {
314     MainWindow *main_w;
315
316 #ifdef _WIN32
317     int                  opt;
318 #endif
319     int                  ret_val;
320     char               **ws_argv = argv;
321
322 #ifdef _WIN32
323     WSADATA              wsaData;
324 #endif  /* _WIN32 */
325
326     char                *rf_path;
327     int                  rf_open_errno;
328     char                *gdp_path, *dp_path;
329 #ifdef HAVE_LIBPCAP
330     gchar               *err_str;
331     int                  status;
332 #else
333     gboolean             capture_option_specified = FALSE;
334 #ifdef _WIN32
335 #ifdef HAVE_AIRPCAP
336     gchar               *err_str;
337 #endif
338 #endif
339 #endif
340     commandline_capture_param_info_t capture_param_info;
341     commandline_param_info_t commandline_info;
342
343     QString              dfilter, read_filter;
344
345     /* Initialize the capture arguments */
346     memset(&capture_param_info, 0, sizeof(capture_param_info));
347
348     cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
349
350     // In Qt 5, C strings are treated always as UTF-8 when converted to
351     // QStrings; in Qt 4, the codec must be set to make that happen
352 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
353     // Hopefully we won't have to use QString::fromUtf8() in as many places.
354     QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
355     QTextCodec::setCodecForCStrings(utf8codec);
356     // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
357     QTextCodec::setCodecForTr(utf8codec);
358 #endif
359
360     /* Set the C-language locale to the native environment. */
361     // The GTK+ UI calls this. Should we as well?
362     //setlocale(LC_ALL, "");
363 #ifdef _WIN32
364     // QCoreApplication clobbers argv. Let's have a local copy.
365     ws_argv = (char **) g_malloc(sizeof(char *) * argc);
366     for (opt = 0; opt < argc; opt++) {
367         ws_argv[opt] = argv[opt];
368     }
369     arg_list_utf_16to8(argc, ws_argv);
370     create_app_running_mutex();
371 #endif /* _WIN32 */
372
373     /*
374      * Get credential information for later use, and drop privileges
375      * before doing anything else.
376      * Let the user know if anything happened.
377      */
378     init_process_policies();
379     relinquish_special_privs_perm();
380
381     /*
382      * Attempt to get the pathname of the executable file.
383      */
384     /* init_progfile_dir_error = */ init_progfile_dir(ws_argv[0],
385         (int (*)(int, char **)) get_gui_compiled_info);
386     g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
387
388 #ifdef _WIN32
389     /* Load wpcap if possible. Do this before collecting the run-time version information */
390     load_wpcap();
391
392     /* ... and also load the packet.dll from wpcap */
393     wpcap_packet_load();
394
395 #ifdef HAVE_AIRPCAP
396     /* Load the airpcap.dll.  This must also be done before collecting
397      * run-time version information. */
398     load_airpcap();
399 #if 0
400     airpcap_dll_ret_val = load_airpcap();
401
402     switch (airpcap_dll_ret_val) {
403     case AIRPCAP_DLL_OK:
404         /* load the airpcap interfaces */
405         g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
406
407         if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
408             if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
409                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
410                 g_free(err_str);
411             }
412             airpcap_if_active = NULL;
413
414         } else {
415
416             /* select the first ad default (THIS SHOULD BE CHANGED) */
417             airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
418         }
419         break;
420     /*
421      * XXX - Maybe we need to warn the user if one of the following happens???
422      */
423     case AIRPCAP_DLL_OLD:
424         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
425         break;
426
427     case AIRPCAP_DLL_ERROR:
428         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
429         break;
430
431     case AIRPCAP_DLL_NOT_FOUND:
432         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
433         break;
434     }
435 #endif
436 #endif /* HAVE_AIRPCAP */
437 #endif /* _WIN32 */
438
439     /* Get the compile-time version information string */
440     capture_param_info.comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
441                                               get_gui_compiled_info);
442
443     /* Assemble the run-time version information string */
444     capture_param_info.runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
445
446     profile_store_persconffiles(TRUE);
447
448     /* Read the profile independent recent file.  We have to do this here so we can */
449     /* set the profile before it can be set from the command line parameter */
450     if (!recent_read_static(&rf_path, &rf_open_errno)) {
451         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
452                       "Could not open common recent file\n\"%s\": %s.",
453                       rf_path, strerror(rf_open_errno));
454         g_free(rf_path);
455     }
456
457     commandline_capture_options(argc, ws_argv, &capture_param_info);
458
459 #ifdef _WIN32
460     reset_library_path();
461 #endif
462
463     /* Create The Wireshark app */
464     WiresharkApplication ws_app(argc, argv);
465
466     /* initialize the funnel mini-api */
467     // xxx qtshark
468     //initialize_funnel_ops();
469
470     AirPDcapInitContext(&airpdcap_ctx);
471
472     QString locale;
473     QString cf_name;
474     unsigned int in_file_type = WTAP_TYPE_AUTO;
475
476     /* Add it to the information to be reported on a crash. */
477     ws_add_crash_info("Wireshark %s\n"
478            "\n"
479            "%s"
480            "\n"
481            "%s",
482         get_ws_vcs_version_info(), capture_param_info.comp_info_str->str, capture_param_info.runtime_info_str->str);
483
484 #ifdef _WIN32
485     /* Start windows sockets */
486     WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
487 #endif  /* _WIN32 */
488
489     /* Read the profile dependent (static part) of the recent file. */
490     /* Only the static part of it will be read, as we don't have the gui now to fill the */
491     /* recent lists which is done in the dynamic part. */
492     /* We have to do this already here, so command line parameters can overwrite these values. */
493     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
494         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
495                       "Could not open recent file\n\"%s\": %s.",
496                       rf_path, g_strerror(rf_open_errno));
497         g_free(rf_path);
498     }
499     wsApp->applyCustomColorsFromRecent();
500
501     // Initialize our language
502     read_language_prefs();
503     locale = QString(language);
504     wsApp->loadLanguage(locale);
505
506     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
507
508     // Init the main window (and splash)
509     main_w = new(MainWindow);
510     main_w->show();
511     // We may not need a queued connection here but it would seem to make sense
512     // to force the issue.
513     main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
514             main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
515
516     /* Init the "Open file" dialog directory */
517     /* (do this after the path settings are processed) */
518     if (recent.gui_fileopen_remembered_dir &&
519         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
520       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
521     } else {
522       wsApp->setLastOpenDir(get_persdatafile_dir());
523     }
524
525 #ifdef Q_OS_UNIX
526     // Replicates behavior in gtk_init();
527     signal(SIGPIPE, SIG_IGN);
528 #endif
529
530     set_console_log_handler();
531
532 #ifdef HAVE_LIBPCAP
533     /* Set the initial values in the capture options. This might be overwritten
534        by preference settings and then again by the command line parameters. */
535     capture_opts_init(&global_capture_opts);
536 #endif
537
538     init_report_err(vfailure_alert_box, open_failure_alert_box,
539                     read_failure_alert_box, write_failure_alert_box);
540
541     init_open_routines();
542
543     /* Register all dissectors; we must do this before checking for the
544        "-G" flag, as the "-G" flag dumps information registered by the
545        dissectors, and we must do it before we read the preferences, in
546        case any dissectors register preferences. */
547     if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
548                    splash_update, NULL)) {
549         SimpleDialog::displayQueuedMessages(main_w);
550         return 2;
551     }
552
553 #ifdef HAVE_PLUGINS
554     /* Register all the plugin types we have. */
555     epan_register_plugin_types(); /* Types known to libwireshark */
556     wtap_register_plugin_types(); /* Types known to libwiretap */
557     codec_register_plugin_types(); /* Types known to libwscodecs */
558
559     /* Scan for plugins.  This does *not* call their registration routines;
560        that's done later. */
561     scan_plugins();
562
563     /* Register all libwiretap plugin modules. */
564     register_all_wiretap_modules();
565
566     /* Register all audio codec plugins. */
567     register_all_codecs();
568 #endif
569
570     splash_update(RA_LISTENERS, NULL, NULL);
571
572     /* Register all tap listeners; we do this before we parse the arguments,
573        as the "-z" argument can specify a registered tap. */
574
575     /* we register the plugin taps before the other taps because
576             stats_tree taps plugins will be registered as tap listeners
577             by stats_tree_stat.c and need to registered before that */
578 #ifdef HAVE_PLUGINS
579     register_all_plugin_tap_listeners();
580 #endif
581
582 #ifdef HAVE_EXTCAP
583     extcap_register_preferences();
584 #endif
585
586     register_all_tap_listeners();
587     conversation_table_set_gui_info(init_conversation_table);
588     hostlist_table_set_gui_info(init_endpoint_table);
589     srt_table_iterate_tables(register_service_response_tables, NULL);
590     rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
591     new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
592
593     if (ex_opt_count("read_format") > 0) {
594         in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
595     }
596
597     splash_update(RA_PREFERENCES, NULL, NULL);
598
599     commandline_info.prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
600
601     /* Initialize commandline_info with default values */
602     commandline_info.jump_backwards = SD_FORWARD;
603     commandline_info.go_to_packet = 0;
604     commandline_info.jfilter = NULL;
605     commandline_info.cf_name = NULL;
606     commandline_info.rfilter = NULL;
607     commandline_info.dfilter = NULL;
608 #ifdef HAVE_LIBPCAP
609     commandline_info.start_capture = FALSE;
610     commandline_info.list_link_layer_types = FALSE;
611 #endif
612     commandline_info.disable_protocol_slist = NULL;
613     commandline_info.enable_heur_slist = NULL;
614     commandline_info.disable_heur_slist = NULL;
615
616     /* Transfer capture option data to other options structure */
617     commandline_info.arg_error = capture_param_info.arg_error;
618 #ifndef HAVE_LIBPCAP
619     commandline_info.capture_option_specified = capture_param_info.capture_option_specified;
620 #endif
621
622     /* Now get our args */
623     commandline_other_options(argc, argv, &commandline_info, TRUE);
624
625     /* Convert some command-line parameters to QStrings */
626     if (commandline_info.cf_name != NULL)
627         cf_name = QString(commandline_info.cf_name);
628     if (commandline_info.rfilter != NULL)
629         read_filter = QString(commandline_info.rfilter);
630     if (commandline_info.dfilter != NULL)
631         dfilter = QString(commandline_info.dfilter);
632
633     /* Removed thread code:
634      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
635      */
636
637     // XXX Is there a better place to set the timestamp format & precision?
638     timestamp_set_type(recent.gui_time_format);
639     timestamp_set_precision(recent.gui_time_precision);
640     timestamp_set_seconds_type (recent.gui_seconds_format);
641
642 #ifdef HAVE_LIBPCAP
643     fill_in_local_interfaces(main_window_update);
644
645     if (commandline_info.start_capture && commandline_info.list_link_layer_types) {
646         /* Specifying *both* is bogus. */
647         cmdarg_err("You can't specify both -L and a live capture.");
648         exit(1);
649     }
650
651     if (commandline_info.list_link_layer_types) {
652         /* We're supposed to list the link-layer types for an interface;
653            did the user also specify a capture file to be read? */
654         if (!cf_name.isEmpty()) {
655             /* Yes - that's bogus. */
656             cmdarg_err("You can't specify -L and a capture file to be read.");
657         exit(1);
658         }
659         /* No - did they specify a ring buffer option? */
660         if (global_capture_opts.multi_files_on) {
661             cmdarg_err("Ring buffer requested, but a capture isn't being done.");
662             exit(1);
663         }
664     } else {
665         /* We're supposed to do a live capture; did the user also specify
666            a capture file to be read? */
667         if (commandline_info.start_capture && !cf_name.isEmpty()) {
668             /* Yes - that's bogus. */
669             cmdarg_err("You can't specify both a live capture and a capture file to be read.");
670             exit(1);
671         }
672
673         /* No - was the ring buffer option specified and, if so, does it make
674            sense? */
675         if (global_capture_opts.multi_files_on) {
676             /* Ring buffer works only under certain conditions:
677              a) ring buffer does not work with temporary files;
678              b) real_time_mode and multi_files_on are mutually exclusive -
679              real_time_mode takes precedence;
680              c) it makes no sense to enable the ring buffer if the maximum
681              file size is set to "infinite". */
682             if (global_capture_opts.save_file == NULL) {
683                 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
684                 global_capture_opts.multi_files_on = FALSE;
685             }
686             if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
687                 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
688                 /* XXX - this must be redesigned as the conditions changed */
689             }
690         }
691     }
692
693     if (commandline_info.start_capture || commandline_info.list_link_layer_types) {
694         /* We're supposed to do a live capture or get a list of link-layer
695            types for a live capture device; if the user didn't specify an
696            interface to use, pick a default. */
697         status = capture_opts_default_iface_if_necessary(&global_capture_opts,
698         ((commandline_info.prefs_p->capture_device) && (*commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(commandline_info.prefs_p->capture_device) : NULL);
699         if (status != 0) {
700             exit(status);
701         }
702     }
703
704     if (commandline_info.list_link_layer_types) {
705         /* Get the list of link-layer types for the capture devices. */
706         if_capabilities_t *caps;
707         guint i;
708         interface_t device;
709         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
710
711             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
712             if (device.selected) {
713 #if defined(HAVE_PCAP_CREATE)
714                 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
715 #else
716                 caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
717 #endif
718                 if (caps == NULL) {
719                     cmdarg_err("%s", err_str);
720                     g_free(err_str);
721                     exit(2);
722                 }
723             if (caps->data_link_types == NULL) {
724                 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
725                 exit(2);
726             }
727 #ifdef _WIN32
728             create_console();
729 #endif /* _WIN32 */
730 #if defined(HAVE_PCAP_CREATE)
731             capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
732 #else
733             capture_opts_print_if_capabilities(caps, device.name, FALSE);
734 #endif
735 #ifdef _WIN32
736             destroy_console();
737 #endif /* _WIN32 */
738             free_if_capabilities(caps);
739             }
740         }
741         exit(0);
742     }
743
744     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
745     capture_opts_trim_ring_num_files(&global_capture_opts);
746 #endif /* HAVE_LIBPCAP */
747
748     /* Notify all registered modules that have had any of their preferences
749        changed either from one of the preferences file or from the command
750        line that their preferences have changed. */
751     prefs_apply_all();
752     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
753
754 #ifdef HAVE_LIBPCAP
755     if ((global_capture_opts.num_selected == 0) &&
756             (prefs.capture_device != NULL)) {
757         guint i;
758         interface_t device;
759         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
760             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
761             if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
762                 device.selected = TRUE;
763                 global_capture_opts.num_selected++;
764                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
765                 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
766                 break;
767             }
768         }
769     }
770 #endif
771
772     /* disabled protocols as per configuration file */
773     if (gdp_path == NULL && dp_path == NULL) {
774         set_disabled_protos_list();
775         set_disabled_heur_dissector_list();
776     }
777
778     if(commandline_info.disable_protocol_slist) {
779         GSList *proto_disable;
780         for (proto_disable = commandline_info.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
781         {
782             proto_disable_proto_by_name((char*)proto_disable->data);
783         }
784     }
785
786     if(commandline_info.enable_heur_slist) {
787         GSList *heur_enable;
788         for (heur_enable = commandline_info.enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
789         {
790             proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
791         }
792     }
793
794     if(commandline_info.disable_heur_slist) {
795         GSList *heur_disable;
796         for (heur_disable = commandline_info.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
797         {
798             proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
799         }
800     }
801
802     build_column_format_array(&CaptureFile::globalCapFile()->cinfo, commandline_info.prefs_p->num_cols, TRUE);
803     wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
804     wsApp->emitAppSignal(WiresharkApplication::RecentFilesRead); // Must be emitted after PreferencesChanged.
805
806     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
807
808     /* For update of WindowTitle (When use gui.window_title preference) */
809     main_w->setWSWindowTitle();
810 ////////
811
812     /* Read the dynamic part of the recent file, as we have the gui now ready for
813        it. */
814     if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
815         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
816                       "Could not open recent file\n\"%s\": %s.",
817                       rf_path, g_strerror(rf_open_errno));
818         g_free(rf_path);
819     }
820
821     packet_list_enable_color(recent.packet_list_colorize);
822
823     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
824     packet_list_enable_color(TRUE);
825
826 ////////
827
828
829 ////////
830     gchar* err_msg = NULL;
831     if (!color_filters_init(&err_msg, color_filter_add_cb)) {
832         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
833         g_free(err_msg);
834     }
835
836 ////////
837
838 #ifdef HAVE_LIBPCAP
839     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
840     if (!commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
841         global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
842     }
843 #else /* HAVE_LIBPCAP */
844     ////////
845 #endif /* HAVE_LIBPCAP */
846
847     wsApp->allSystemsGo();
848     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
849     SimpleDialog::displayQueuedMessages(main_w);
850
851     /* User could specify filename, or display filter, or both */
852     if (!dfilter.isEmpty())
853         main_w->filterPackets(dfilter, false);
854     if (!cf_name.isEmpty()) {
855         if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
856
857             /* Open stat windows; we do so after creating the main window,
858                to avoid Qt warnings, and after successfully opening the
859                capture file, so we know we have something to compute stats
860                on, and after registering all dissectors, so that MATE will
861                have registered its field array and we can have a tap filter
862                with one of MATE's late-registered fields as part of the
863                filter. */
864             start_requested_stats();
865
866             if(commandline_info.go_to_packet != 0) {
867                 /* Jump to the specified frame number, kept for backward
868                    compatibility. */
869                 cf_goto_frame(CaptureFile::globalCapFile(), commandline_info.go_to_packet);
870             }
871         }
872     }
873 #ifdef HAVE_LIBPCAP
874     else {
875         if (commandline_info.start_capture) {
876             if (global_capture_opts.save_file != NULL) {
877                 /* Save the directory name for future file dialogs. */
878                 /* (get_dirname overwrites filename) */
879                 gchar *s = g_strdup(global_capture_opts.save_file);
880                 set_last_open_dir(get_dirname(s));
881                 g_free(s);
882             }
883             /* "-k" was specified; start a capture. */
884 //            show_main_window(FALSE);
885             check_and_warn_user_startup(cf_name);
886
887             /* If no user interfaces were specified on the command line,
888                copy the list of selected interfaces to the set of interfaces
889                to use for this capture. */
890             if (global_capture_opts.ifaces->len == 0)
891                 collect_ifaces(&global_capture_opts);
892             CaptureFile::globalCapFile()->window = main_w;
893             if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
894                 /* The capture started.  Open stat windows; we do so after creating
895                    the main window, to avoid GTK warnings, and after successfully
896                    opening the capture file, so we know we have something to compute
897                    stats on, and after registering all dissectors, so that MATE will
898                    have registered its field array and we can have a tap filter with
899                    one of MATE's late-registered fields as part of the filter. */
900                 start_requested_stats();
901             }
902         }
903     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
904         if (!commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
905             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
906         }
907     }
908 #endif /* HAVE_LIBPCAP */
909
910     profile_store_persconffiles(FALSE);
911
912     ret_val = wsApp->exec();
913
914     epan_cleanup();
915
916     AirPDcapDestroyContext(&airpdcap_ctx);
917
918 #ifdef _WIN32
919     /* Shutdown windows sockets */
920     WSACleanup();
921
922     /* For some unknown reason, the "atexit()" call in "create_console()"
923        doesn't arrange that "destroy_console()" be called when we exit,
924        so we call it here if a console was created. */
925     destroy_console();
926 #endif /* _WIN32 */
927
928     return ret_val;
929 }
930
931 /*
932  * Editor modelines
933  *
934  * Local Variables:
935  * c-basic-offset: 4
936  * tab-width: 8
937  * indent-tabs-mode: nil
938  * End:
939  *
940  * ex: set shiftwidth=4 tabstop=8 expandtab:
941  * :indentSize=4:tabSize=8:noTabs=true:
942  */