When any of our executables start on Windows create or open a "Wireshark
[metze/wireshark/wip.git] / ui / qt / main.cpp
1 /* main.cpp
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "wireshark_application.h"
25 #include "main_window.h"
26
27 #include "config.h"
28 #include <ctype.h>
29 #include "globals.h"
30
31 #include <glib.h>
32
33 #ifndef HAVE_GETOPT
34 #  include "wsutil/wsgetopt.h"
35 #else
36 #  include <getopt.h>
37 #endif
38
39 #ifdef HAVE_LIBPORTAUDIO
40 #  include <portaudio.h>
41 #endif /* HAVE_LIBPORTAUDIO */
42
43 #include <wsutil/crash_info.h>
44
45 #include <epan/epan.h>
46 #include <epan/filesystem.h>
47 #include <wsutil/privileges.h>
48 #include <epan/epan_dissect.h>
49 #include <epan/timestamp.h>
50 #include <epan/packet.h>
51 #include <epan/plugins.h>
52 #include <epan/dfilter/dfilter.h>
53 #include <epan/strutil.h>
54 #include <epan/addr_resolv.h>
55 #include <epan/emem.h>
56 #include <epan/ex-opt.h>
57 #include <epan/funnel.h>
58 #include <epan/expert.h>
59 #include <epan/frequency-utils.h>
60 #include <epan/prefs.h>
61 #include <epan/prefs-int.h>
62 #include <epan/tap.h>
63 #include <epan/stat_cmd_args.h>
64 #include <epan/uat.h>
65 #include <epan/column.h>
66
67 /* general (not Qt specific) */
68 #include "file.h"
69 #include "summary.h"
70 #include "disabled_protos.h"
71 #include "color.h"
72 #include "color_filters.h"
73 #include "print.h"
74 #include "register.h"
75 #include "ringbuffer.h"
76 #include "ui/util.h"
77 #include "clopts_common.h"
78 #include "console_io.h"
79 #include "cmdarg_err.h"
80 #include "version_info.h"
81 #include "merge.h"
82 #include "log.h"
83 #include "u3.h"
84 #include <wsutil/file_util.h>
85
86 #include "ui/alert_box.h"
87 #include "ui/capture_globals.h"
88 #include "ui/iface_lists.h"
89 #include "ui/main_statusbar.h"
90 #include "ui/recent.h"
91 #include "ui/simple_dialog.h"
92 #include "ui/ui_util.h"
93
94 #ifdef HAVE_LIBPCAP
95 #  include "capture_ui_utils.h"
96 #  include "capture-pcap-util.h"
97 #  include "capture_ifinfo.h"
98 #  include "capture.h"
99 #  include "capture_sync.h"
100 #endif
101
102 #ifdef _WIN32
103 #  include "capture-wpcap.h"
104 #  include "capture_wpcap_packet.h"
105 #  include <tchar.h> /* Needed for Unicode */
106 #  include <wsutil/unicode-utils.h>
107 #  include <commctrl.h>
108 #  include <shellapi.h>
109 #  include <conio.h>
110 #  include "ui/win32/console_win32.h"
111 #endif /* _WIN32 */
112
113 #ifdef HAVE_AIRPCAP
114 #  include <airpcap.h>
115 #  include "airpcap_loader.h"
116 //#  include "airpcap_dlg.h"
117 //#  include "airpcap_gui_utils.h"
118 #endif
119
120 #include <epan/crypt/airpdcap_ws.h>
121
122 #include <QDebug>
123 #include <QDateTime>
124 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
125 #include <QTextCodec>
126 #endif
127 #include <qtranslator.h>
128 #include <qlocale.h>
129 #include <qlibraryinfo.h>
130
131 capture_file cfile;
132
133 #ifdef HAVE_AIRPCAP
134 int    airpcap_dll_ret_val = -1;
135 #endif
136
137 GString *comp_info_str, *runtime_info_str;
138
139 //static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
140
141 //static guint  tap_update_timer_id;
142
143 static void console_log_handler(const char *log_domain,
144     GLogLevelFlags log_level, const char *message, gpointer user_data);
145
146
147 #ifdef HAVE_LIBPCAP
148 extern capture_options global_capture_opts;
149 #endif
150
151 static void
152 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data )
153 {
154     Q_UNUSED(user_data);
155     wsApp->captureCallback(event, capture_opts);
156 }
157
158 static void
159 main_cf_callback(gint event, gpointer data, gpointer user_data )
160 {
161     Q_UNUSED(user_data);
162     wsApp->captureFileCallback(event, data);
163 }
164
165 /* update the main window */
166 void main_window_update(void)
167 {
168     WiresharkApplication::processEvents();
169 }
170
171 /* exit the main window */
172 void main_window_exit(void)
173 {
174     exit(0);
175 }
176
177 #ifdef HAVE_LIBPCAP
178
179 /* quit a nested main window */
180 void main_window_nested_quit(void)
181 {
182 //    if (gtk_main_level() > 0)
183     WiresharkApplication::quit();
184 }
185
186 /* quit the main window */
187 void main_window_quit(void)
188 {
189     WiresharkApplication::quit();
190 }
191
192 #endif /* HAVE_LIBPCAP */
193
194
195 // xxx copied from ../gtk/main.c
196 static void
197 print_usage(gboolean print_ver) {
198     FILE *output;
199
200 #ifdef _WIN32
201     create_console();
202 #endif
203
204     if (print_ver) {
205         output = stdout;
206         fprintf(output, "Wireshark " VERSION "%s\n"
207                 "Interactively dump and analyze network traffic.\n"
208                 "See http://www.wireshark.org for more information.\n"
209                 "\n"
210                 "%s",
211                 wireshark_svnversion, get_copyright_info());
212     } else {
213         output = stderr;
214     }
215     fprintf(output, "\n");
216     fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
217     fprintf(output, "\n");
218
219 #ifdef HAVE_LIBPCAP
220     fprintf(output, "Capture interface:\n");
221     fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
222     fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
223     fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
224     fprintf(output, "  -p                       don't capture in promiscuous mode\n");
225     fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
226     fprintf(output, "  -Q                       quit Wireshark after capturing\n");
227     fprintf(output, "  -S                       update packet display when new packets are captured\n");
228     fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
229 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
230     fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
231 #endif
232     fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
233     fprintf(output, "  -D                       print list of interfaces and exit\n");
234     fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
235     fprintf(output, "\n");
236     fprintf(output, "Capture stop conditions:\n");
237     fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
238     fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
239     fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
240     fprintf(output, "                              files:NUM - stop after NUM files\n");
241     /*fprintf(output, "\n");*/
242     fprintf(output, "Capture output:\n");
243     fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
244     fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
245     fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
246 #endif  /* HAVE_LIBPCAP */
247
248     /*fprintf(output, "\n");*/
249     fprintf(output, "Input file:\n");
250     fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
251
252     fprintf(output, "\n");
253     fprintf(output, "Processing:\n");
254     fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
255     fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
256     fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
257
258     fprintf(output, "\n");
259     fprintf(output, "User interface:\n");
260     fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
261     fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
262     fprintf(output, "  -J <jump filter>         jump to the first packet matching the (display)\n");
263     fprintf(output, "                           filter\n");
264     fprintf(output, "  -j                       search backwards for a matching packet after \"-J\"\n");
265     fprintf(output, "  -m <font>                set the font name used for most text\n");
266     fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
267     fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
268     fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
269     fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
270
271     fprintf(output, "\n");
272     fprintf(output, "Output:\n");
273     fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
274
275     fprintf(output, "\n");
276     fprintf(output, "Miscellaneous:\n");
277     fprintf(output, "  -h                       display this help and exit\n");
278     fprintf(output, "  -v                       display version info and exit\n");
279     fprintf(output, "  -P <key>:<path>          persconf:path - personal configuration files\n");
280     fprintf(output, "                           persdata:path - personal data files\n");
281     fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
282     fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
283 #ifndef _WIN32
284     fprintf(output, "  --display=DISPLAY        X display to use\n");
285 #endif
286
287 #ifdef _WIN32
288     destroy_console();
289 #endif
290 }
291
292 // xxx copied from ../gtk/main.c
293 static void
294 show_version(void)
295 {
296 #ifdef _WIN32
297     create_console();
298 #endif
299
300     printf(PACKAGE " " VERSION "%s\n"
301            "\n"
302            "%s"
303            "\n"
304            "%s"
305            "\n"
306            "%s",
307            wireshark_svnversion, get_copyright_info(), comp_info_str->str,
308            runtime_info_str->str);
309
310 #ifdef _WIN32
311     destroy_console();
312 #endif
313 }
314
315 /*
316  * Print to the standard error.  On Windows, create a console for the
317  * standard error to show up on, if necessary.
318  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
319  * terminal isn't the standard error?
320  */
321 // xxx copied from ../gtk/main.c
322 void
323 vfprintf_stderr(const char *fmt, va_list ap)
324 {
325 #ifdef _WIN32
326     create_console();
327 #endif
328     vfprintf(stderr, fmt, ap);
329 }
330
331 void
332 fprintf_stderr(const char *fmt, ...)
333 {
334     va_list ap;
335
336     va_start(ap, fmt);
337     vfprintf_stderr(fmt, ap);
338     va_end(ap);
339 }
340
341 /*
342  * Report an error in command-line arguments.
343  * Creates a console on Windows.
344  */
345 // xxx copied from ../gtk/main.c
346 void
347 cmdarg_err(const char *fmt, ...)
348 {
349     va_list ap;
350
351     fprintf_stderr("wireshark: ");
352     va_start(ap, fmt);
353     vfprintf_stderr(fmt, ap);
354     va_end(ap);
355     fprintf_stderr("\n");
356 }
357
358 /*
359  * Report additional information for an error in command-line arguments.
360  * Creates a console on Windows.
361  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
362  * terminal isn't the standard error?
363  */
364 // xxx copied from ../gtk/main.c
365 void
366 cmdarg_err_cont(const char *fmt, ...)
367 {
368     va_list ap;
369
370     va_start(ap, fmt);
371     vfprintf_stderr(fmt, ap);
372     fprintf_stderr("\n");
373     va_end(ap);
374 }
375
376 static void
377 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
378                     const char *message, gpointer user_data)
379 {
380     Q_UNUSED(user_data);
381     QString level;
382     QString hmsz = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
383
384 // xxx qtshark: We want all of the messages for now.
385 //    /* ignore log message, if log_level isn't interesting based
386 //     upon the console log preferences.
387 //     If the preferences haven't been loaded loaded yet, display the
388 //     message anyway.
389
390 //     The default console_log_level preference value is such that only
391 //       ERROR, CRITICAL and WARNING level messages are processed;
392 //       MESSAGE, INFO and DEBUG level messages are ignored.  */
393 //    if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
394 //       prefs.console_log_level != 0) {
395 //        return;
396
397         switch(log_level & G_LOG_LEVEL_MASK) {
398         case G_LOG_LEVEL_ERROR:
399             level = "Err ";
400             break;
401         case G_LOG_LEVEL_CRITICAL:
402             level = "Crit";
403             break;
404         case G_LOG_LEVEL_WARNING:
405             level = "Warn";
406             break;
407         case G_LOG_LEVEL_MESSAGE:
408             level = "Msg ";
409             break;
410         case G_LOG_LEVEL_INFO:
411             level = "Info";
412             break;
413         case G_LOG_LEVEL_DEBUG:
414             level = "Dbg ";
415             break;
416         default:
417             qDebug("%s unknown log_level %u", hmsz.toUtf8().constData(), log_level);
418             g_assert_not_reached();
419         }
420
421         qDebug("%s %s %s %s", hmsz.toUtf8().constData(), log_domain, level.toUtf8().constData(), message);
422     }
423
424 // xxx based from ../gtk/main.c:get_gtk_compiled_info
425 static void
426 get_qt_compiled_info(GString *str)
427 {
428   g_string_append(str, "with ");
429   g_string_append_printf(str,
430 #ifdef QT_VERSION
431                      "Qt %s ", QT_VERSION_STR);
432 #else
433                     "Qt (version unknown) ");
434 #endif
435 }
436
437 // xxx copied from ../gtk/main.c
438 static void
439 get_gui_compiled_info(GString *str)
440 {
441   epan_get_compiled_version_info(str);
442
443   g_string_append(str, ", ");
444 #ifdef HAVE_LIBPORTAUDIO
445 #ifdef PORTAUDIO_API_1
446   g_string_append(str, "with PortAudio <= V18");
447 #else /* PORTAUDIO_API_1 */
448   g_string_append(str, "with ");
449   g_string_append(str, Pa_GetVersionText());
450 #endif /* PORTAUDIO_API_1 */
451 #else /* HAVE_LIBPORTAUDIO */
452   g_string_append(str, "without PortAudio");
453 #endif /* HAVE_LIBPORTAUDIO */
454
455   g_string_append(str, ", ");
456 #ifdef HAVE_AIRPCAP
457   get_compiled_airpcap_version(str);
458 #else
459   g_string_append(str, "without AirPcap");
460 #endif
461 }
462
463 // xxx copied from ../gtk/main.c
464 static void
465 get_gui_runtime_info(GString *str)
466 {
467   epan_get_runtime_version_info(str);
468
469 #ifdef HAVE_AIRPCAP
470   g_string_append(str, ", ");
471   get_runtime_airpcap_version(str);
472 #endif
473
474
475   if(u3_active()) {
476     g_string_append(str, ", ");
477     u3_runtime_info(str);
478   }
479
480 }
481
482 /* And now our feature presentation... [ fade to music ] */
483 int main(int argc, char *argv[])
484 {
485     WiresharkApplication ws_app(argc, argv);
486     MainWindow *main_w;
487
488 //    char                *init_progfile_dir_error;
489 //    char                *s;
490     int                  opt;
491 //    gboolean             arg_error = FALSE;
492
493 //    extern int           info_update_freq;  /* Found in about_dlg.c. */
494 //    const gchar         *filter;
495
496 #ifdef _WIN32
497     WSADATA            wsaData;
498 #endif  /* _WIN32 */
499
500     char                *rf_path;
501     int                  rf_open_errno;
502     char                *gdp_path, *dp_path;
503     int                  err;
504 #ifdef HAVE_LIBPCAP
505 //    gboolean             start_capture = FALSE;
506 //    gboolean             list_link_layer_types = FALSE;
507     GList               *if_list;
508     gchar               *err_str;
509 #else
510     gboolean             capture_option_specified = FALSE;
511 #ifdef _WIN32
512 #ifdef HAVE_AIRPCAP
513     gchar               *err_str;
514 #endif
515 #endif
516 #endif
517 //    gint                 pl_size = 280, tv_size = 95, bv_size = 75;
518 //    gchar               *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
519 //    dfilter_t           *rfcode = NULL;
520 //    gboolean             rfilter_parse_failed = FALSE;
521     e_prefs             *prefs_p;
522 //    char                 badopt;
523     GLogLevelFlags       log_flags;
524 //    guint                go_to_packet = 0;
525 //    gboolean             jump_backwards = FALSE;
526 //    dfilter_t           *jump_to_filter = NULL;
527 //    int                  optind_initial;
528     int                  status;
529
530     //initialize language !
531     create_app_running_mutex();
532
533     QString locale = QLocale::system().name();
534
535     g_log(NULL, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
536     QTranslator translator;
537     translator.load(QString(":/i18n/qtshark_") + locale);
538     ws_app.installTranslator(&translator);
539
540     QTranslator qtTranslator;
541     qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
542     ws_app.installTranslator(&qtTranslator);
543
544     // In Qt 5, C strings are treated always as UTF-8 when converted to
545     // QStrings; in Qt 4, the codec must be set to make that happen
546 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
547     // Hopefully we won't have to use QString::fromUtf8() in as many places.
548     QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
549     QTextCodec::setCodecForCStrings(utf8codec);
550     // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
551     QTextCodec::setCodecForTr(utf8codec);
552 #endif
553
554     main_w = new(MainWindow);
555 //    w->setEnabled(false);
556     main_w->show();
557     // We may not need a queued connection here but it would seem to make sense
558     // to force the issue.
559     main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString&)),
560             main_w, SLOT(openCaptureFile(QString&)));
561
562     // XXX Should the remaining code be in WiresharkApplcation::WiresharkApplication?
563 #ifdef HAVE_LIBPCAP
564 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
565 #define OPTSTRING_B "B:"
566 #else
567 #define OPTSTRING_B ""
568 #endif  /* _WIN32 or HAVE_PCAP_CREATE */
569 #else /* HAVE_LIBPCAP */
570 #define OPTSTRING_B ""
571 #endif  /* HAVE_LIBPCAP */
572
573 #ifdef HAVE_PCAP_CREATE
574 #define OPTSTRING_I "I"
575 #else
576 #define OPTSTRING_I ""
577 #endif
578
579 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:u:vw:X:y:z:"
580
581     static const char optstring[] = OPTSTRING;
582
583     /* Assemble the compile-time version information string */
584     comp_info_str = g_string_new("Compiled ");
585
586     // xxx qtshark
587     get_compiled_version_info(comp_info_str, get_qt_compiled_info, get_gui_compiled_info);
588
589     /* Assemble the run-time version information string */
590     runtime_info_str = g_string_new("Running ");
591     // xxx qtshark
592     get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
593
594     ws_add_crash_info(PACKAGE " " VERSION "%s\n"
595            "\n"
596            "%s"
597            "\n"
598            "%s",
599         wireshark_svnversion, comp_info_str->str, runtime_info_str->str);
600
601     /*
602      * Get credential information for later use, and drop privileges
603      * before doing anything else.
604      * Let the user know if anything happened.
605      */
606     init_process_policies();
607     relinquish_special_privs_perm();
608
609     /*
610      * Attempt to get the pathname of the executable file.
611      */
612     /* init_progfile_dir_error = */ init_progfile_dir(argv[0], main);
613     g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
614
615     /* initialize the funnel mini-api */
616     // xxx qtshark
617     //initialize_funnel_ops();
618
619     AirPDcapInitContext(&airpdcap_ctx);
620
621 // xxx qtshark
622 #ifdef _WIN32
623   /* Load wpcap if possible. Do this before collecting the run-time version information */
624   load_wpcap();
625
626   /* ... and also load the packet.dll from wpcap */
627   wpcap_packet_load();
628
629 #ifdef HAVE_AIRPCAP
630     /* Load the airpcap.dll.  This must also be done before collecting
631      * run-time version information. */
632     airpcap_dll_ret_val = load_airpcap();
633
634     switch (airpcap_dll_ret_val) {
635     case AIRPCAP_DLL_OK:
636         /* load the airpcap interfaces */
637         airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
638
639         if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
640             if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
641                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
642                 g_free(err_str);
643             }
644             airpcap_if_active = NULL;
645
646         } else {
647
648             /* select the first ad default (THIS SHOULD BE CHANGED) */
649             airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
650         }
651         break;
652 #if 0
653     /*
654      * XXX - Maybe we need to warn the user if one of the following happens???
655      */
656     case AIRPCAP_DLL_OLD:
657         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
658         break;
659
660     case AIRPCAP_DLL_ERROR:
661         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
662         break;
663
664     case AIRPCAP_DLL_NOT_FOUND:
665         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
666         break;
667 #endif
668     }
669 #endif /* HAVE_AIRPCAP */
670
671     /* Start windows sockets */
672     WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
673 #endif  /* _WIN32 */
674
675     profile_store_persconffiles (TRUE);
676
677     /* Read the profile independent recent file.  We have to do this here so we can */
678     /* set the profile before it can be set from the command line parameterts */
679     recent_read_static(&rf_path, &rf_open_errno);
680     if (rf_path != NULL && rf_open_errno != 0) {
681         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
682                       "Could not open common recent file\n\"%s\": %s.",
683                       rf_path, strerror(rf_open_errno));
684     }
685
686     /* "pre-scan" the command line parameters, if we have "console only"
687        parameters.  We do this so we don't start GTK+ if we're only showing
688        command-line help or version information.
689
690        XXX - this pre-scan is done before we start GTK+, so we haven't
691        run gtk_init() on the arguments.  That means that GTK+ arguments
692        have not been removed from the argument list; those arguments
693        begin with "--", and will be treated as an error by getopt().
694
695        We thus ignore errors - *and* set "opterr" to 0 to suppress the
696        error messages. */
697     opterr = 0;
698     // optind_initial = optind;
699     while ((opt = getopt(argc, argv, optstring)) != -1) {
700         switch (opt) {
701         case 'C':        /* Configuration Profile */
702             if (profile_exists (optarg, FALSE)) {
703                 set_profile_name (optarg);
704             } else {
705                 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
706                 exit(1);
707             }
708             break;
709         case 'D':        /* Print a list of capture devices and exit */
710 #ifdef HAVE_LIBPCAP
711             if_list = capture_interface_list(&err, &err_str);
712             if (if_list == NULL) {
713                 switch (err) {
714                 case CANT_GET_INTERFACE_LIST:
715                     cmdarg_err("%s", err_str);
716                     g_free(err_str);
717                     break;
718
719                 case NO_INTERFACES_FOUND:
720                     cmdarg_err("There are no interfaces on which a capture can be done");
721                     break;
722                 }
723                 exit(2);
724             }
725             capture_opts_print_interfaces(if_list);
726             free_interface_list(if_list);
727             exit(0);
728 #else
729             capture_option_specified = TRUE;
730             arg_error = TRUE;
731 #endif
732             break;
733         case 'h':        /* Print help and exit */
734             print_usage(TRUE);
735             exit(0);
736             break;
737 #ifdef _WIN32
738         case 'i':
739             if (strcmp(optarg, "-") == 0)
740                 set_stdin_capture(TRUE);
741             break;
742 #endif
743         case 'P':        /* Path settings - change these before the Preferences and alike are processed */
744             status = filesystem_opt(opt, optarg);
745             if(status != 0) {
746                 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
747                 exit(status);
748             }
749             break;
750         case 'v':        /* Show version and exit */
751             show_version();
752             exit(0);
753             break;
754         case 'X':
755             /*
756            *  Extension command line options have to be processed before
757            *  we call epan_init() as they are supposed to be used by dissectors
758            *  or taps very early in the registration process.
759            */
760             ex_opt_add(optarg);
761             break;
762         case '?':        /* Ignore errors - the "real" scan will catch them. */
763             break;
764         }
765     }
766
767     /* Init the "Open file" dialog directory */
768     /* (do this after the path settings are processed) */
769
770     /* Read the profile dependent (static part) of the recent file. */
771     /* Only the static part of it will be read, as we don't have the gui now to fill the */
772     /* recent lists which is done in the dynamic part. */
773     /* We have to do this already here, so command line parameters can overwrite these values. */
774     recent_read_profile_static(&rf_path, &rf_open_errno);
775     if (rf_path != NULL && rf_open_errno != 0) {
776       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
777             "Could not open recent file\n\"%s\": %s.",
778             rf_path, g_strerror(rf_open_errno));
779     }
780
781     if (recent.gui_fileopen_remembered_dir &&
782         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
783       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
784     } else {
785       wsApp->setLastOpenDir(get_persdatafile_dir());
786     }
787
788 #ifdef HAVE_LIBPCAP
789   capture_callback_add(main_capture_callback, NULL);
790 #endif
791     cf_callback_add(main_cf_callback, NULL);
792
793     /* Arrange that if we have no console window, and a GLib message logging
794        routine is called to log a message, we pop up a console window.
795
796        We do that by inserting our own handler for all messages logged
797        to the default domain; that handler pops up a console if necessary,
798        and then calls the default handler. */
799
800     /* We might want to have component specific log levels later ... */
801
802     log_flags = (GLogLevelFlags) (
803             G_LOG_LEVEL_ERROR|
804             G_LOG_LEVEL_CRITICAL|
805             G_LOG_LEVEL_WARNING|
806             G_LOG_LEVEL_MESSAGE|
807             G_LOG_LEVEL_INFO|
808             G_LOG_LEVEL_DEBUG|
809             G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION );
810
811     g_log_set_handler(NULL,
812                       log_flags,
813                       console_log_handler, NULL /* user_data */);
814     g_log_set_handler(LOG_DOMAIN_MAIN,
815                       log_flags,
816                       console_log_handler, NULL /* user_data */);
817
818 #ifdef HAVE_LIBPCAP
819     g_log_set_handler(LOG_DOMAIN_CAPTURE,
820                       log_flags,
821                       console_log_handler, NULL /* user_data */);
822     g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
823                       log_flags,
824                       console_log_handler, NULL /* user_data */);
825
826     /* Set the initial values in the capture options. This might be overwritten
827        by preference settings and then again by the command line parameters. */
828     capture_opts_init(&global_capture_opts, &cfile);
829 #endif
830
831     /* Register all dissectors; we must do this before checking for the
832        "-G" flag, as the "-G" flag dumps information registered by the
833        dissectors, and we must do it before we read the preferences, in
834        case any dissectors register preferences. */
835     epan_init(register_all_protocols,register_all_protocol_handoffs,
836               splash_update, NULL,
837               failure_alert_box,open_failure_alert_box,read_failure_alert_box,
838               write_failure_alert_box
839               );
840
841     splash_update(RA_LISTENERS, NULL, NULL);
842
843     /* Register all tap listeners; we do this before we parse the arguments,
844        as the "-z" argument can specify a registered tap. */
845
846     /* we register the plugin taps before the other taps because
847             stats_tree taps plugins will be registered as tap listeners
848             by stats_tree_stat.c and need to registered before that */
849
850     g_log(NULL, G_LOG_LEVEL_DEBUG, "plugin_dir: %s", get_plugin_dir());
851   #ifdef HAVE_PLUGINS
852     register_all_plugin_tap_listeners();
853   #endif
854
855 //    register_all_tap_listeners();
856
857     splash_update(RA_PREFERENCES, NULL, NULL);
858
859     prefs_p = ws_app.readConfigurationFiles (&gdp_path, &dp_path);
860     /* Removed thread code:
861      * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
862      */
863
864     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: timestamp types should be set elsewhere");
865     timestamp_set_type(TS_RELATIVE);
866     timestamp_set_precision(TS_PREC_AUTO_USEC);
867     timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
868
869 /////////
870
871 #ifdef HAVE_LIBPCAP
872     fill_in_local_interfaces();
873 //  if (start_capture && list_link_layer_types) {
874 //    /* Specifying *both* is bogus. */
875 //    cmdarg_err("You can't specify both -L and a live capture.");
876 //    exit(1);
877 //  }
878
879 //  if (list_link_layer_types) {
880 //    /* We're supposed to list the link-layer types for an interface;
881 //       did the user also specify a capture file to be read? */
882 //    if (cf_name) {
883 //      /* Yes - that's bogus. */
884 //      cmdarg_err("You can't specify -L and a capture file to be read.");
885 //      exit(1);
886 //    }
887 //    /* No - did they specify a ring buffer option? */
888 //    if (global_capture_opts.multi_files_on) {
889 //      cmdarg_err("Ring buffer requested, but a capture isn't being done.");
890 //      exit(1);
891 //    }
892 //  } else {
893 //    /* We're supposed to do a live capture; did the user also specify
894 //       a capture file to be read? */
895 //    if (start_capture && cf_name) {
896 //      /* Yes - that's bogus. */
897 //      cmdarg_err("You can't specify both a live capture and a capture file to be read.");
898 //      exit(1);
899 //    }
900
901 //    /* No - was the ring buffer option specified and, if so, does it make
902 //       sense? */
903 //    if (global_capture_opts.multi_files_on) {
904 //      /* Ring buffer works only under certain conditions:
905 //      a) ring buffer does not work with temporary files;
906 //      b) real_time_mode and multi_files_on are mutually exclusive -
907 //         real_time_mode takes precedence;
908 //      c) it makes no sense to enable the ring buffer if the maximum
909 //         file size is set to "infinite". */
910 //      if (global_capture_opts.save_file == NULL) {
911 //        cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
912 //        global_capture_opts.multi_files_on = FALSE;
913 //      }
914 //      if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
915 //        cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
916 //        /* XXX - this must be redesigned as the conditions changed */
917 //      }
918 //    }
919 //  }
920
921 //  if (start_capture || list_link_layer_types) {
922 //    /* Did the user specify an interface to use? */
923 //    status = capture_opts_trim_iface(&global_capture_opts,
924 //        (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL);
925 //    if (status != 0) {
926 //      exit(status);
927 //    }
928 //  }
929
930 //  if (list_link_layer_types) {
931 //    /* Get the list of link-layer types for the capture devices. */
932 //    if_capabilities_t *caps;
933 //    guint i;
934 //    interface_t device;
935 //    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
936
937 //      device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
938 //      if (device.selected) {
939 //#if defined(HAVE_PCAP_CREATE)
940 //        caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str);
941 //#else
942 //        caps = capture_get_if_capabilities(device.name, FALSE, &err_str);
943 //#endif
944 //        if (caps == NULL) {
945 //          cmdarg_err("%s", err_str);
946 //          g_free(err_str);
947 //          exit(2);
948 //        }
949 //        if (caps->data_link_types == NULL) {
950 //          cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
951 //          exit(2);
952 //        }
953 //#if defined(HAVE_PCAP_CREATE)
954 //        capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
955 //#else
956 //        capture_opts_print_if_capabilities(caps, device.name, FALSE);
957 //#endif
958 //        free_if_capabilities(caps);
959 //      }
960 //    }
961 //    exit(0);
962 //  }
963
964     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
965     capture_opts_trim_ring_num_files(&global_capture_opts);
966 #endif /* HAVE_LIBPCAP */
967
968     /* Notify all registered modules that have had any of their preferences
969        changed either from one of the preferences file or from the command
970        line that their preferences have changed. */
971     prefs_apply_all();
972     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
973
974 #ifdef HAVE_LIBPCAP
975     if ((global_capture_opts.num_selected == 0) &&
976             (prefs.capture_device != NULL)) {
977         guint i;
978         interface_t device;
979         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
980             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
981             if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
982                 device.selected = TRUE;
983                 global_capture_opts.num_selected++;
984                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
985                 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
986                 break;
987             }
988         }
989     }
990 #endif
991
992     /* disabled protocols as per configuration file */
993     if (gdp_path == NULL && dp_path == NULL) {
994         set_disabled_protos_list();
995     }
996
997     build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
998
999 //    /* read in rc file from global and personal configuration paths. */
1000 //    rc_file = get_datafile_path(RC_FILE);
1001 //  #if GTK_CHECK_VERSION(3,0,0)
1002 //    /* XXX resolve later */
1003 //  #else
1004 //    gtk_rc_parse(rc_file);
1005 //    g_free(rc_file);
1006 //    rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
1007 //    gtk_rc_parse(rc_file);
1008 //  #endif
1009 //    g_free(rc_file);
1010
1011     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
1012
1013 ////////
1014
1015     /* Read the dynamic part of the recent file, as we have the gui now ready for
1016   it. */
1017     recent_read_dynamic(&rf_path, &rf_open_errno);
1018     if (rf_path != NULL && rf_open_errno != 0) {
1019       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1020                     "Could not open recent file\n\"%s\": %s.",
1021                     rf_path, g_strerror(rf_open_errno));
1022     }
1023
1024     color_filters_enable(recent.packet_list_colorize);
1025
1026     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
1027     color_filters_enable(TRUE);
1028
1029 ////////
1030
1031 //    switch (user_font_apply()) {
1032 //    case FA_SUCCESS:
1033 //        break;
1034 //    case FA_FONT_NOT_RESIZEABLE:
1035 //        /* "user_font_apply()" popped up an alert box. */
1036 //        /* turn off zooming - font can't be resized */
1037 //    case FA_FONT_NOT_AVAILABLE:
1038 //        /* XXX - did we successfully load the un-zoomed version earlier?
1039 //        If so, this *probably* means the font is available, but not at
1040 //        this particular zoom level, but perhaps some other failure
1041 //        occurred; I'm not sure you can determine which is the case,
1042 //        however. */
1043 //        /* turn off zooming - zoom level is unavailable */
1044 //    default:
1045 //        /* in any other case than FA_SUCCESS, turn off zooming */
1046 ////        recent.gui_zoom_level = 0;
1047 //        /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
1048 //        break;
1049 //    }
1050
1051 ////////
1052     color_filters_init();
1053
1054 ////////
1055
1056 //    w->setEnabled(true);
1057     wsApp->allSystemsGo();
1058     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
1059
1060     g_main_loop_new(NULL, FALSE);
1061     return wsApp->exec();
1062 }
1063
1064 /*
1065  * Editor modelines
1066  *
1067  * Local Variables:
1068  * c-basic-offset: 4
1069  * tab-width: 8
1070  * indent-tabs-mode: nil
1071  * End:
1072  *
1073  * ex: set shiftwidth=4 tabstop=8 expandtab:
1074  * :indentSize=4:tabSize=8:noTabs=true:
1075  */