Have separate proto_construct_match_selected_string() and
[obnox/wireshark/wip.git] / gtk / main.c
1 /* main.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10  *                              needed by dissect routines
11  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
12  *
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <gtk/gtk.h>
34 #include <gdk/gdkkeysyms.h>
35
36 #include <string.h>
37 #include <ctype.h>
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef NEED_STRERROR_H
44 #include "strerror.h"
45 #endif
46
47 #ifdef NEED_GETOPT_H
48 #include "getopt.h"
49 #endif
50
51 #ifdef _WIN32 /* Needed for console I/O */
52 #include <fcntl.h>
53 #include <conio.h>
54 #endif
55
56 #ifdef HAVE_LIBPORTAUDIO
57 #include <portaudio.h>
58 #endif /* HAVE_LIBPORTAUDIO */
59
60 #include <epan/epan.h>
61 #include <epan/filesystem.h>
62 #include <epan/privileges.h>
63 #include <epan/epan_dissect.h>
64 #include <epan/timestamp.h>
65 #include <epan/packet.h>
66 #include <epan/plugins.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/strutil.h>
69 #include <epan/addr_resolv.h>
70 #include <epan/emem.h>
71 #include <epan/ex-opt.h>
72 #include <epan/funnel.h>
73 #include <epan/expert.h>
74
75 /* general (not GTK specific) */
76 #include "file.h"
77 #include "summary.h"
78 #include "filters.h"
79 #include "disabled_protos.h"
80 #include <epan/prefs.h>
81 #include "filter_dlg.h"
82 #include "layout_prefs.h"
83 #include "color.h"
84 #include "color_filters.h"
85 #include "print.h"
86 #include "simple_dialog.h"
87 #include "register.h"
88 #include <epan/prefs-int.h>
89 #include "ringbuffer.h"
90 #include "../ui_util.h"
91 #include <epan/tap.h>
92 #include <epan/stat_cmd_args.h>
93 #include "util.h"
94 #include "clopts_common.h"
95 #include "cmdarg_err.h"
96 #include "version_info.h"
97 #include "merge.h"
98 #include "u3.h"
99
100
101 #ifdef HAVE_LIBPCAP
102 #include "capture-pcap-util.h"
103 #include "capture.h"
104 #include "capture_sync.h"
105 #endif
106
107 #ifdef _WIN32
108 #include "capture-wpcap.h"
109 #include "capture_wpcap_packet.h"
110 #include <tchar.h> /* Needed for Unicode */
111 #if GTK_MAJOR_VERSION >= 2
112 #include <commctrl.h>
113 #endif /* GTK_MAJOR_VERSION >= 2 */
114 #endif /* _WIN32 */
115
116 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
117 #include "ethclist.h"
118 #endif
119
120 /* GTK related */
121 #include "statusbar.h"
122 #include "alert_box.h"
123 #if 0
124 #include "dlg_utils.h"
125 #endif
126 #include "file_dlg.h"
127 #include "gtkglobals.h"
128 #include "colors.h"
129 #include "gui_utils.h"
130 #include "compat_macros.h"
131
132 #include "main.h"
133 #include "menu.h"
134 #include "../main_window.h"
135 #include "../menu.h"
136 #include "capture_file_dlg.h"
137 #include <epan/column.h>
138 #include "proto_draw.h"
139 #include "keys.h"
140 #include "packet_win.h"
141 #include "toolbar.h"
142 #include "find_dlg.h"
143 #include "packet_list.h"
144 #include "recent.h"
145 #include "follow_dlg.h"
146 #include "font_utils.h"
147 #include "about_dlg.h"
148 #include "help_dlg.h"
149 #include "decode_as_dlg.h"
150 #include "webbrowser.h"
151 #include "capture_dlg.h"
152 #include "capture_ui_utils.h"
153 #include "log.h"
154 #include "../epan/emem.h"
155 #include "file_util.h"
156 #include "../image/wsicon16.xpm"
157 #include "../image/wsicon32.xpm"
158 #include "../image/wsicon48.xpm"
159 #include "../image/wsicon64.xpm"
160 #include "../image/wsiconcap16.xpm"
161 #include "../image/wsiconcap32.xpm"
162 #include "../image/wsiconcap48.xpm"
163
164 #ifdef HAVE_AIRPCAP
165 #include <airpcap.h>
166 #include "airpcap_loader.h"
167 #include "airpcap_dlg.h"
168 #include "airpcap_gui_utils.h"
169
170 #include "./gtk/toolbar.h"
171
172 #include "./image/toolbar/wep_closed_24.xpm"
173 #endif
174
175 /*
176  * Files under personal and global preferences directories in which
177  * GTK settings for Wireshark are stored.
178  */
179 #define RC_FILE "gtkrc"
180
181 #ifdef HAVE_LIBPCAP
182 #define DEF_READY_MESSAGE " Ready to load or capture"
183 #else
184 #define DEF_READY_MESSAGE " Ready to load file"
185 #endif
186
187 capture_file cfile;
188 GtkWidget   *main_display_filter_widget=NULL;
189 GtkWidget   *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
190 static GtkWidget   *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
191 static GtkWidget   *main_first_pane, *main_second_pane;
192 static GtkWidget   *status_pane;
193 static GtkWidget   *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
194
195 #ifdef HAVE_AIRPCAP
196 GtkWidget *airpcap_tb;
197 static GtkWidget *driver_warning_dialog;
198 static int    airpcap_dll_ret_val = -1;
199 #endif
200
201 static GtkWidget        *info_bar;
202 static GtkWidget    *packets_bar = NULL;
203 static GtkWidget    *welcome_pane;
204 static guint            main_ctx, file_ctx, help_ctx;
205 static guint        packets_ctx;
206 static gchar        *packets_str = NULL;
207 GString *comp_info_str, *runtime_info_str;
208 gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
209
210 #ifdef _WIN32
211 static gboolean has_console;    /* TRUE if app has console */
212 static void destroy_console(void);
213 #endif
214 static void console_log_handler(const char *log_domain,
215     GLogLevelFlags log_level, const char *message, gpointer user_data);
216
217 #ifdef HAVE_LIBPCAP
218 static gboolean list_link_layer_types;
219 capture_options global_capture_opts;
220 capture_options *capture_opts = &global_capture_opts;
221 #endif
222
223 gboolean block_toolbar_signals = FALSE;
224
225 static void create_main_window(gint, gint, gint, e_prefs*);
226 static void show_main_window(gboolean);
227 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
228 static void main_save_window_geometry(GtkWidget *widget);
229
230 #define E_DFILTER_CM_KEY          "display_filter_combo"
231 #define E_DFILTER_FL_KEY          "display_filter_list"
232
233 /* Match selected byte pattern */
234 static void
235 match_selected_cb_do(gpointer data, int action, gchar *text)
236 {
237     GtkWidget           *filter_te;
238     char                *cur_filter, *new_filter;
239
240     if (!text)
241         return;
242     g_assert(data);
243     filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
244     g_assert(filter_te);
245
246     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
247
248     switch (action&MATCH_SELECTED_MASK) {
249
250     case MATCH_SELECTED_REPLACE:
251         new_filter = g_strdup(text);
252         break;
253
254     case MATCH_SELECTED_AND:
255         if ((!cur_filter) || (0 == strlen(cur_filter)))
256             new_filter = g_strdup(text);
257         else
258             new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
259         break;
260
261     case MATCH_SELECTED_OR:
262         if ((!cur_filter) || (0 == strlen(cur_filter)))
263             new_filter = g_strdup(text);
264         else
265             new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
266         break;
267
268     case MATCH_SELECTED_NOT:
269         new_filter = g_strconcat("!(", text, ")", NULL);
270         break;
271
272     case MATCH_SELECTED_AND_NOT:
273         if ((!cur_filter) || (0 == strlen(cur_filter)))
274             new_filter = g_strconcat("!(", text, ")", NULL);
275         else
276             new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
277         break;
278
279     case MATCH_SELECTED_OR_NOT:
280         if ((!cur_filter) || (0 == strlen(cur_filter)))
281             new_filter = g_strconcat("!(", text, ")", NULL);
282         else
283             new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
284         break;
285
286     default:
287         g_assert_not_reached();
288         new_filter = NULL;
289         break;
290     }
291
292     /* Free up the copy we got of the old filter text. */
293     g_free(cur_filter);
294
295     /* create a new one and set the display filter entry accordingly */
296     gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
297
298     /* Run the display filter so it goes in effect. */
299     if (action&MATCH_SELECTED_APPLY_NOW)
300         main_filter_packets(&cfile, new_filter, FALSE);
301
302     /* Free up the new filter text. */
303     g_free(new_filter);
304 }
305
306 void
307 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
308 {
309     char *filter;
310
311     if (cfile.finfo_selected) {
312         filter = proto_construct_match_selected_string(cfile.finfo_selected,
313                                                        cfile.edt);
314         if (filter != NULL)
315             match_selected_cb_do((data ? data : w), action, filter);
316     }
317 }
318
319
320 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
321 {
322     gchar *selected_proto_url;
323     gchar *proto_abbrev = data;
324
325
326     switch(btn) {
327     case(ESD_BTN_OK):
328         if (cfile.finfo_selected) {
329             /* open wiki page using the protocol abbreviation */
330             selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
331             browser_open_url(selected_proto_url);
332             g_free(selected_proto_url);
333         }
334         break;
335     case(ESD_BTN_CANCEL):
336         break;
337     default:
338         g_assert_not_reached();
339     }
340 }
341
342
343 void
344 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
345 {
346     int field_id;
347     const gchar *proto_abbrev;
348     gpointer  dialog;
349
350
351     if (cfile.finfo_selected) {
352         /* convert selected field to protocol abbreviation */
353         /* XXX - could this conversion be simplified? */
354         field_id = cfile.finfo_selected->hfinfo->id;
355         /* if the selected field isn't a protocol, get it's parent */
356         if(!proto_registrar_is_protocol(field_id)) {
357             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
358         }
359
360         proto_abbrev = proto_registrar_get_abbrev(field_id);
361
362         /* ask the user if the wiki page really should be opened */
363         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
364                     PRIMARY_TEXT_START "Open Wireshark Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
365                     "\n"
366                     "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
367                     "\n"
368                     "The Wireshark Wiki is a collaborative approach to provide information\n"
369                     "about Wireshark in several ways (not limited to protocol specifics).\n"
370                     "\n"
371                     "This Wiki is new, so the page of the selected protocol\n"
372                     "may not exist and/or may not contain valuable information.\n"
373                     "\n"
374                     "As everyone can edit the Wiki and add new content (or extend existing),\n"
375                     "you are encouraged to add information if you can.\n"
376                     "\n"
377                     "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
378                     "\n"
379                     "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
380                     "which will save you a lot of editing and will give a consistent look over the pages.",
381                     proto_abbrev, proto_abbrev);
382         simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
383     }
384 }
385
386
387 void
388 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
389 {
390     int field_id;
391     const gchar *proto_abbrev;
392     gchar *selected_proto_url;
393
394
395     if (cfile.finfo_selected) {
396         /* convert selected field to protocol abbreviation */
397         /* XXX - could this conversion be simplified? */
398         field_id = cfile.finfo_selected->hfinfo->id;
399         /* if the selected field isn't a protocol, get it's parent */
400         if(!proto_registrar_is_protocol(field_id)) {
401             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
402         }
403
404         proto_abbrev = proto_registrar_get_abbrev(field_id);
405
406         /* open reference page using the protocol abbreviation */
407         selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
408         browser_open_url(selected_proto_url);
409         g_free(selected_proto_url);
410     }
411 }
412
413 static gchar *
414 get_text_from_packet_list(gpointer data)
415 {
416     gint        row = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY));
417     gint        column = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY));
418     frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
419     epan_dissect_t *edt;
420     gchar      *buf=NULL;
421     int         len;
422     int         err;
423     gchar       *err_info;
424
425     if (fdata != NULL) {
426         if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
427                        cfile.pd, fdata->cap_len, &err, &err_info)) {
428             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
429                           cf_read_error_message(err, err_info), cfile.filename);
430             return NULL;
431         }
432
433         edt = epan_dissect_new(FALSE, FALSE);
434         epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
435                          &cfile.cinfo);
436         epan_dissect_fill_in_columns(edt);
437
438         if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
439             strlen(cfile.cinfo.col_expr_val[column]) != 0) {
440             len = strlen(cfile.cinfo.col_expr[column]) +
441                   strlen(cfile.cinfo.col_expr_val[column]) + 5;
442             buf = ep_alloc0(len);
443             g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
444                      cfile.cinfo.col_expr_val[column]);
445         }
446
447         epan_dissect_free(edt);
448     }
449
450     return buf;
451 }
452
453 void
454 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
455 {
456     match_selected_cb_do(data,
457         action,
458         get_text_from_packet_list(data));
459 }
460
461 /* This function allows users to right click in the details window and copy the text
462  * information to the operating systems clipboard.
463  *
464  * We first check to see if a string representation is setup in the tree and then
465  * read the string. If not available then we try to grab the value. If all else
466  * fails we display a message to the user to indicate the copy could not be completed.
467  */
468 void
469 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
470 {
471         GString *gtk_text_str = g_string_new("");
472     char labelstring[256];
473     char *stringpointer = labelstring;
474
475     if (cfile.finfo_selected->rep->representation != 0) {
476         g_string_sprintfa(gtk_text_str, "%s", cfile.finfo_selected->rep->representation);   /* Get the represented data */
477     }
478     if (gtk_text_str->len == 0) {                                                           /* If no representation then... */
479         proto_item_fill_label(cfile.finfo_selected, stringpointer);                         /* Try to read the value */
480         g_string_sprintfa(gtk_text_str, "%s", stringpointer);
481     }
482     if (gtk_text_str->len == 0) {                                                           /* Could not get item so display error msg */
483         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
484     }
485     else
486     {
487         copy_to_clipboard(gtk_text_str);                     /* Copy string to clipboard */
488     }
489     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
490 }
491
492
493 /* XXX: use a preference for this setting! */
494 static guint dfilter_combo_max_recent = 10;
495
496 /* add a display filter to the combo box */
497 /* Note: a new filter string will replace an old identical one */
498 static gboolean
499 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
500   GList     *li;
501   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
502
503
504   /* GtkCombos don't let us get at their list contents easily, so we maintain
505      our own filter list, and feed it to gtk_combo_set_popdown_strings when
506      a new filter is added. */
507     li = g_list_first(dfilter_list);
508     while (li) {
509         /* If the filter is already in the list, remove the old one and
510                  * append the new one at the latest position (at g_list_append() below) */
511                 if (li->data && strcmp(s, li->data) == 0) {
512           dfilter_list = g_list_remove(dfilter_list, li->data);
513                   break;
514                 }
515       li = li->next;
516     }
517
518     dfilter_list = g_list_append(dfilter_list, s);
519     OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
520     gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), dfilter_list);
521     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), g_list_last(dfilter_list)->data);
522
523     return TRUE;
524 }
525
526
527 /* write all non empty display filters (until maximum count)
528  * of the combo box GList to the user's recent file */
529 void
530 dfilter_recent_combo_write_all(FILE *rf) {
531   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
532   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
533   GList     *li;
534   guint      max_count = 0;
535
536
537   /* write all non empty display filter strings to the recent file (until max count) */
538   li = g_list_first(dfilter_list);
539   while ( li && (max_count++ <= dfilter_combo_max_recent) ) {
540     if (strlen(li->data)) {
541       fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", (char *)li->data);
542     }
543     li = li->next;
544   }
545 }
546
547 /* empty the combobox entry field */
548 void
549 dfilter_combo_add_empty(void) {
550   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
551
552   gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), "");
553 }
554
555
556 /* add a display filter coming from the user's recent file to the dfilter combo box */
557 gboolean
558 dfilter_combo_add_recent(gchar *s) {
559   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
560   char      *dup;
561
562   dup = g_strdup(s);
563   if (!dfilter_combo_add(filter_cm, dup)) {
564     g_free(dup);
565     return FALSE;
566   }
567
568   return TRUE;
569 }
570
571
572 /* call cf_filter_packets() and add this filter string to the recent filter list */
573 gboolean
574 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
575 {
576   GtkCombo  *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
577   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
578   GList     *li;
579   gboolean   add_filter = TRUE;
580   gboolean   free_filter = TRUE;
581   char      *s;
582   cf_status_t cf_status;
583
584   /* we'll crash later on if dftext is NULL */
585   g_assert(dftext != NULL);
586
587   s = g_strdup(dftext);
588
589   /* GtkCombos don't let us get at their list contents easily, so we maintain
590      our own filter list, and feed it to gtk_combo_set_popdown_strings when
591      a new filter is added. */
592   cf_status = cf_filter_packets(cf, s, force);
593   if (cf_status == CF_OK) {
594     li = g_list_first(dfilter_list);
595     while (li) {
596       if (li->data && strcmp(s, li->data) == 0)
597         add_filter = FALSE;
598       li = li->next;
599     }
600
601     if (add_filter) {
602       /* trim list size first */
603       while (g_list_length(dfilter_list) >= dfilter_combo_max_recent) {
604         dfilter_list = g_list_remove(dfilter_list, g_list_first(dfilter_list)->data);
605       }
606
607       free_filter = FALSE;
608       dfilter_list = g_list_append(dfilter_list, s);
609       OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
610       gtk_combo_set_popdown_strings(filter_cm, dfilter_list);
611       gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(dfilter_list)->data);
612     }
613   }
614   if (free_filter)
615     g_free(s);
616
617   return (cf_status == CF_OK);
618 }
619
620
621 /* Run the current display filter on the current packet set, and
622    redisplay. */
623 static void
624 filter_activate_cb(GtkWidget *w _U_, gpointer data)
625 {
626   const char *s;
627
628   s = gtk_entry_get_text(GTK_ENTRY(data));
629
630   main_filter_packets(&cfile, s, FALSE);
631 }
632
633 /* redisplay with no display filter */
634 static void
635 filter_reset_cb(GtkWidget *w, gpointer data _U_)
636 {
637   GtkWidget *filter_te = NULL;
638
639   if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
640     gtk_entry_set_text(GTK_ENTRY(filter_te), "");
641   }
642   main_filter_packets(&cfile, "", FALSE);
643 }
644
645 /* mark as reference time frame */
646 static void
647 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
648   if (row == -1)
649     return;
650   if (set) {
651     frame->flags.ref_time=1;
652   } else {
653     frame->flags.ref_time=0;
654   }
655   cf_reftime_packets(&cfile);
656 }
657
658
659 GtkWidget *reftime_dialog = NULL;
660
661 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
662 {
663     switch(btn) {
664     case(ESD_BTN_YES):
665         timestamp_set_type(TS_RELATIVE);
666         recent.gui_time_format  = TS_RELATIVE;
667         cf_change_time_formats(&cfile);
668         break;
669     case(ESD_BTN_NO):
670         break;
671     default:
672         g_assert_not_reached();
673     }
674
675     if (cfile.current_frame) {
676       /* XXX hum, should better have a "cfile->current_row" here ... */
677       set_frame_reftime(!cfile.current_frame->flags.ref_time,
678                      cfile.current_frame,
679                      packet_list_find_row_from_data(cfile.current_frame));
680     }
681 }
682
683
684 void
685 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
686 {
687
688   switch(action){
689   case REFTIME_TOGGLE:
690     if (cfile.current_frame) {
691         if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
692             reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
693                 PRIMARY_TEXT_START "Switch to the appropriate Time Display Format?" PRIMARY_TEXT_END "\n\n"
694                 "Time References don't work well with the currently selected Time Display Format.\n\n"
695                 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?");
696             simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
697         } else {
698             /* XXX hum, should better have a "cfile->current_row" here ... */
699             set_frame_reftime(!cfile.current_frame->flags.ref_time,
700                               cfile.current_frame,
701                               packet_list_find_row_from_data(cfile.current_frame));
702         }
703     }
704     break;
705   case REFTIME_FIND_NEXT:
706     find_previous_next_frame_with_filter("frame.ref_time", FALSE);
707     break;
708   case REFTIME_FIND_PREV:
709     find_previous_next_frame_with_filter("frame.ref_time", TRUE);
710     break;
711   }
712 }
713
714 void
715 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
716 {
717     find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
718 }
719
720 void
721 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
722 {
723     find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
724 }
725
726 #if GTK_MAJOR_VERSION < 2
727 static void
728 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
729                         gpointer user_data _U_)
730 #else
731 static void
732 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
733 #endif
734 {
735     field_info   *finfo;
736     gchar        *help_str = NULL;
737     gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
738                                           N < 4294967296 */
739     gboolean      has_blurb = FALSE;
740     guint         length = 0, byte_len;
741     GtkWidget    *byte_view;
742     const guint8 *byte_data;
743 #if GTK_MAJOR_VERSION >= 2
744     GtkTreeModel *model;
745     GtkTreeIter   iter;
746 #endif
747
748 #if GTK_MAJOR_VERSION >= 2
749     /* if nothing is selected */
750     if (!gtk_tree_selection_get_selected(sel, &model, &iter))
751     {
752         /*
753          * Which byte view is displaying the current protocol tree
754          * row's data?
755          */
756         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
757         if (byte_view == NULL)
758             return;     /* none */
759
760         byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
761         if (byte_data == NULL)
762             return;     /* none */
763
764         cf_unselect_field(&cfile);
765         packet_hex_print(byte_view, byte_data,
766                          cfile.current_frame, NULL, byte_len);
767         return;
768     }
769     gtk_tree_model_get(model, &iter, 1, &finfo, -1);
770 #else
771     g_assert(node);
772     finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
773 #endif
774     if (!finfo) return;
775
776     set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
777
778     byte_view = get_notebook_bv_ptr(byte_nb_ptr);
779     byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
780     g_assert(byte_data != NULL);
781
782     cfile.finfo_selected = finfo;
783     set_menus_for_selected_tree_row(&cfile);
784
785     if (finfo->hfinfo) {
786         if (finfo->hfinfo->blurb != NULL &&
787             finfo->hfinfo->blurb[0] != '\0') {
788             has_blurb = TRUE;
789             length = strlen(finfo->hfinfo->blurb);
790         } else {
791             length = strlen(finfo->hfinfo->name);
792         }
793         if (finfo->length == 0) {
794             len_str[0] = '\0';
795         } else if (finfo->length == 1) {
796             strcpy (len_str, ", 1 byte");
797         } else {
798             g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
799         }
800         statusbar_pop_field_msg();      /* get rid of current help msg */
801         if (length) {
802             help_str = g_strdup_printf("%s (%s)%s",
803                     (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
804                     finfo->hfinfo->abbrev, len_str);
805             statusbar_push_field_msg(help_str);
806             g_free(help_str);
807         } else {
808             /*
809              * Don't show anything if the field name is zero-length;
810              * the pseudo-field for "proto_tree_add_text()" is such
811              * a field, and we don't want "Text (text)" showing up
812              * on the status line if you've selected such a field.
813              *
814              * XXX - there are zero-length fields for which we *do*
815              * want to show the field name.
816              *
817              * XXX - perhaps the name and abbrev field should be null
818              * pointers rather than null strings for that pseudo-field,
819              * but we'd have to add checks for null pointers in some
820              * places if we did that.
821              *
822              * Or perhaps protocol tree items added with
823              * "proto_tree_add_text()" should have -1 as the field index,
824              * with no pseudo-field being used, but that might also
825              * require special checks for -1 to be added.
826              */
827             statusbar_push_field_msg("");
828         }
829     }
830
831     packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
832                      byte_len);
833 }
834
835 #if GTK_MAJOR_VERSION < 2
836 static void
837 tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
838                           gpointer user_data _U_)
839 {
840         GtkWidget       *byte_view;
841         const guint8    *data;
842         guint           len;
843
844         /*
845          * Which byte view is displaying the current protocol tree
846          * row's data?
847          */
848         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
849         if (byte_view == NULL)
850                 return; /* none */
851
852         data = get_byte_view_data_and_length(byte_view, &len);
853         if (data == NULL)
854                 return; /* none */
855
856         cf_unselect_field(&cfile);
857         packet_hex_print(byte_view, data, cfile.current_frame, NULL, len);
858 }
859 #endif
860
861 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
862   if (cfile.edt->tree)
863     collapse_all_tree(cfile.edt->tree, tree_view);
864 }
865
866 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
867   if (cfile.edt->tree)
868     expand_all_tree(cfile.edt->tree, tree_view);
869 }
870
871 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
872 #if GTK_MAJOR_VERSION < 2
873   GtkCTreeNode *node;
874 #else
875   GtkTreePath  *path;
876 #endif
877
878 #if GTK_MAJOR_VERSION < 2
879   node = gtk_ctree_find_by_row_data(GTK_CTREE(tree_view), NULL, cfile.finfo_selected);
880   if(node) {
881     /* the mouse position is at an entry, expand that one */
882   gtk_ctree_expand_recursive(GTK_CTREE(tree_view), node);
883   }
884 #else
885   path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
886   if(path) {
887     /* the mouse position is at an entry, expand that one */
888   gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
889   gtk_tree_path_free(path);
890   }
891 #endif
892 }
893
894 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
895   if (cfile.edt->tree) {
896     guint32 tmp = g_resolv_flags;
897     g_resolv_flags = RESOLV_ALL;
898     proto_tree_draw(cfile.edt->tree, tree_view);
899     g_resolv_flags = tmp;
900   }
901 }
902
903 /*
904  * Push a message referring to file access onto the statusbar.
905  */
906 void
907 statusbar_push_file_msg(gchar *msg)
908 {
909     /*g_warning("statusbar_push: %s", msg);*/
910         gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
911 }
912
913 /*
914  * Pop a message referring to file access off the statusbar.
915  */
916 void
917 statusbar_pop_file_msg(void)
918 {
919     /*g_warning("statusbar_pop");*/
920         gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
921 }
922
923 /*
924  * XXX - do we need multiple statusbar contexts?
925  */
926
927 /*
928  * Push a message referring to the currently-selected field onto the statusbar.
929  */
930 void
931 statusbar_push_field_msg(gchar *msg)
932 {
933         gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
934 }
935
936 /*
937  * Pop a message referring to the currently-selected field off the statusbar.
938  */
939 void
940 statusbar_pop_field_msg(void)
941 {
942         gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
943 }
944
945 /*
946  * update the packets statusbar to the current values
947  */
948 void packets_bar_update(void)
949 {
950
951     if(packets_bar) {
952         /* remove old status */
953         if(packets_str) {
954             g_free(packets_str);
955                 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
956         }
957
958         /* do we have any packets? */
959         if(cfile.count) {
960             if(cfile.drops_known) {
961                 packets_str = g_strdup_printf(" P: %u D: %u M: %u Drops: %u",
962                     cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
963             } else {
964                 packets_str = g_strdup_printf(" P: %u D: %u M: %u",
965                     cfile.count, cfile.displayed_count, cfile.marked_count);
966             }
967         } else {
968             packets_str = g_strdup(" No Packets");
969         }
970             gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
971     }
972 }
973
974 void
975 main_set_for_capture_file(gboolean have_capture_file_in)
976 {
977     have_capture_file = have_capture_file_in;
978
979     main_widgets_show_or_hide();
980 }
981
982 gboolean
983 main_do_quit(void)
984 {
985         /* get the current geometry, before writing it to disk */
986         main_save_window_geometry(top_level);
987
988         /* write user's recent file to disk
989          * It is no problem to write this file, even if we do not quit */
990         write_recent();
991
992         /* XXX - should we check whether the capture file is an
993            unsaved temporary file for a live capture and, if so,
994            pop up a "do you want to exit without saving the capture
995            file?" dialog, and then just return, leaving said dialog
996            box to forcibly quit if the user clicks "OK"?
997
998            If so, note that this should be done in a subroutine that
999            returns TRUE if we do so, and FALSE otherwise, and if it
1000            returns TRUE we should return TRUE without nuking anything.
1001
1002            Note that, if we do that, we might also want to check if
1003            an "Update list of packets in real time" capture is in
1004            progress and, if so, ask whether they want to terminate
1005            the capture and discard it, and return TRUE, before nuking
1006            any child capture, if they say they don't want to do so. */
1007
1008 #ifdef HAVE_LIBPCAP
1009         /* Nuke any child capture in progress. */
1010         capture_kill_child(capture_opts);
1011 #endif
1012
1013         /* Are we in the middle of reading a capture? */
1014         if (cfile.state == FILE_READ_IN_PROGRESS) {
1015                 /* Yes, so we can't just close the file and quit, as
1016                    that may yank the rug out from under the read in
1017                    progress; instead, just set the state to
1018                    "FILE_READ_ABORTED" and return - the code doing the read
1019                    will check for that and, if it sees that, will clean
1020                    up and quit. */
1021                 cfile.state = FILE_READ_ABORTED;
1022
1023                 /* Say that the window should *not* be deleted;
1024                    that'll be done by the code that cleans up. */
1025                 return TRUE;
1026         } else {
1027                 /* Close any capture file we have open; on some OSes, you
1028                    can't unlink a temporary capture file if you have it
1029                    open.
1030                    "cf_close()" will unlink it after closing it if
1031                    it's a temporary file.
1032
1033                    We do this here, rather than after the main loop returns,
1034                    as, after the main loop returns, the main window may have
1035                    been destroyed (if this is called due to a "destroy"
1036                    even on the main window rather than due to the user
1037                    selecting a menu item), and there may be a crash
1038                    or other problem when "cf_close()" tries to
1039                    clean up stuff in the main window.
1040
1041                    XXX - is there a better place to put this?
1042                    Or should we have a routine that *just* closes the
1043                    capture file, and doesn't do anything with the UI,
1044                    which we'd call here, and another routine that
1045                    calls that routine and also cleans up the UI, which
1046                    we'd call elsewhere? */
1047                 cf_close(&cfile);
1048
1049                 /* Exit by leaving the main loop, so that any quit functions
1050                    we registered get called. */
1051                 gtk_main_quit();
1052
1053                 /* Say that the window should be deleted. */
1054                 return FALSE;
1055         }
1056 }
1057
1058 static gboolean
1059 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1060 {
1061   gpointer dialog;
1062
1063   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1064 #if GTK_MAJOR_VERSION >= 2
1065     gtk_window_present(GTK_WINDOW(top_level));
1066 #endif
1067     /* user didn't saved his current file, ask him */
1068     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1069                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1070                 "If you quit the program without saving, your capture data will be discarded.");
1071     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1072     return TRUE;
1073   } else {
1074     /* unchanged file, just exit */
1075     /* "main_do_quit()" indicates whether the main window should be deleted. */
1076     return main_do_quit();
1077   }
1078 }
1079
1080
1081
1082 static void
1083 main_load_window_geometry(GtkWidget *widget)
1084 {
1085     window_geometry_t geom;
1086
1087     geom.set_pos        = prefs.gui_geometry_save_position;
1088     geom.x              = recent.gui_geometry_main_x;
1089     geom.y              = recent.gui_geometry_main_y;
1090     geom.set_size       = prefs.gui_geometry_save_size;
1091     if (recent.gui_geometry_main_width > 0 &&
1092         recent.gui_geometry_main_height > 0) {
1093         geom.width          = recent.gui_geometry_main_width;
1094         geom.height         = recent.gui_geometry_main_height;
1095         geom.set_maximized  = prefs.gui_geometry_save_maximized;
1096     } else {
1097         /* We assume this means the width and height weren't set in
1098            the "recent" file (or that there is no "recent" file),
1099            and weren't set to a default value, so we don't set the
1100            size.  (The "recent" file code rejects non-positive width
1101            and height values.) */
1102        geom.set_size = FALSE;
1103     }
1104     geom.maximized      = recent.gui_geometry_main_maximized;
1105
1106     window_set_geometry(widget, &geom);
1107
1108     if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1109         gtk_paned_set_position(GTK_PANED(main_first_pane),  recent.gui_geometry_main_upper_pane);
1110     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
1111         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1112     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_status_pane)
1113         gtk_paned_set_position(GTK_PANED(status_pane),      recent.gui_geometry_status_pane);
1114 }
1115
1116
1117 static void
1118 main_save_window_geometry(GtkWidget *widget)
1119 {
1120     window_geometry_t geom;
1121
1122     window_get_geometry(widget, &geom);
1123
1124     if (prefs.gui_geometry_save_position) {
1125         recent.gui_geometry_main_x = geom.x;
1126             recent.gui_geometry_main_y = geom.y;
1127     }
1128
1129     if (prefs.gui_geometry_save_size) {
1130         recent.gui_geometry_main_width  = geom.width,
1131         recent.gui_geometry_main_height = geom.height;
1132     }
1133
1134 #if GTK_MAJOR_VERSION >= 2
1135     if(prefs.gui_geometry_save_maximized) {
1136         recent.gui_geometry_main_maximized = geom.maximized;
1137     }
1138
1139     recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
1140     recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
1141     recent.gui_geometry_status_pane         = gtk_paned_get_position(GTK_PANED(status_pane));
1142 #endif
1143 }
1144
1145 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1146 {
1147     switch(btn) {
1148     case(ESD_BTN_SAVE):
1149         /* save file first */
1150         file_save_as_cmd(after_save_exit, NULL);
1151         break;
1152     case(ESD_BTN_DONT_SAVE):
1153         main_do_quit();
1154         break;
1155     case(ESD_BTN_CANCEL):
1156         break;
1157     default:
1158         g_assert_not_reached();
1159     }
1160 }
1161
1162 void
1163 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1164 {
1165   gpointer dialog;
1166
1167   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1168     /* user didn't saved his current file, ask him */
1169     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1170                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1171                 "If you quit the program without saving, your capture data will be discarded.");
1172     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1173   } else {
1174     /* unchanged file, just exit */
1175     main_do_quit();
1176   }
1177 }
1178
1179 static void
1180 print_usage(gboolean print_ver) {
1181
1182   FILE *output;
1183
1184 #ifdef _WIN32
1185   create_console();
1186 #endif
1187
1188   if (print_ver) {
1189     output = stdout;
1190     fprintf(output, "Wireshark " VERSION "%s\n"
1191         "Interactively dump and analyze network traffic.\n"
1192         "See http://www.wireshark.org for more information.\n"
1193         "\n"
1194         "%s",
1195         svnversion, get_copyright_info());
1196   } else {
1197     output = stderr;
1198   }
1199   fprintf(output, "\n");
1200   fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1201   fprintf(output, "\n");
1202
1203 #ifdef HAVE_LIBPCAP
1204   fprintf(output, "Capture interface:\n");
1205   fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
1206   fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
1207   fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
1208   fprintf(output, "  -p                       don't capture in promiscuous mode\n");
1209   fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
1210   fprintf(output, "  -Q                       quit Wireshark after capturing\n");
1211   fprintf(output, "  -S                       update packet display when new packets are captured\n");
1212   fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
1213 #ifdef _WIN32
1214   fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
1215 #endif
1216   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
1217   fprintf(output, "  -D                       print list of interfaces and exit\n");
1218   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
1219   fprintf(output, "\n");
1220   fprintf(output, "Capture stop conditions:\n");
1221   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
1222   fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
1223   fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
1224   fprintf(output, "                              files:NUM - stop after NUM files\n");
1225   /*fprintf(output, "\n");*/
1226   fprintf(output, "Capture output:\n");
1227   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1228   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
1229   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
1230 #endif  /* HAVE_LIBPCAP */
1231
1232   /*fprintf(output, "\n");*/
1233   fprintf(output, "Input file:\n");
1234   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
1235
1236   fprintf(output, "\n");
1237   fprintf(output, "Processing:\n");
1238   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
1239   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
1240   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
1241
1242   fprintf(output, "\n");
1243   fprintf(output, "User interface:\n");
1244   fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
1245   fprintf(output, "  -m <font>                set the font name used for most text\n");
1246   fprintf(output, "  -t ad|a|r|d              output format of time stamps (def: r: rel. to first)\n");
1247   fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
1248   fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
1249
1250   fprintf(output, "\n");
1251   fprintf(output, "Output:\n");
1252   fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
1253
1254   fprintf(output, "\n");
1255   fprintf(output, "Miscellaneous:\n");
1256   fprintf(output, "  -h                       display this help and exit\n");
1257   fprintf(output, "  -v                       display version info and exit\n");
1258   fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
1259 #ifndef _WIN32
1260   fprintf(output, "  --display=DISPLAY        X display to use\n");
1261 #endif
1262
1263 #ifdef _WIN32
1264   destroy_console();
1265 #endif
1266 }
1267
1268 static void
1269 show_version(void)
1270 {
1271 #ifdef _WIN32
1272   create_console();
1273 #endif
1274
1275   printf(PACKAGE " " VERSION "%s\n"
1276          "\n"
1277          "%s"
1278          "\n"
1279          "%s"
1280          "\n"
1281          "%s",
1282       svnversion, get_copyright_info(), comp_info_str->str,
1283       runtime_info_str->str);
1284
1285 #ifdef _WIN32
1286   destroy_console();
1287 #endif
1288 }
1289
1290 /*
1291  * Report an error in command-line arguments.
1292  * Creates a console on Windows.
1293  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1294  * terminal isn't the standard error?
1295  */
1296 void
1297 cmdarg_err(const char *fmt, ...)
1298 {
1299   va_list ap;
1300
1301 #ifdef _WIN32
1302   create_console();
1303 #endif
1304   va_start(ap, fmt);
1305   fprintf(stderr, "wireshark: ");
1306   vfprintf(stderr, fmt, ap);
1307   fprintf(stderr, "\n");
1308   va_end(ap);
1309 }
1310
1311 /*
1312  * Report additional information for an error in command-line arguments.
1313  * Creates a console on Windows.
1314  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1315  * terminal isn't the standard error?
1316  */
1317 void
1318 cmdarg_err_cont(const char *fmt, ...)
1319 {
1320   va_list ap;
1321
1322 #ifdef _WIN32
1323   create_console();
1324 #endif
1325   va_start(ap, fmt);
1326   vfprintf(stderr, fmt, ap);
1327   fprintf(stderr, "\n");
1328   va_end(ap);
1329 }
1330
1331 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
1332 /*
1333    Once every 3 seconds we get a callback here which we use to update
1334    the tap extensions. Since Gtk1 is single threaded we dont have to
1335    worry about any locking or critical regions.
1336  */
1337 static gint
1338 update_cb(gpointer data _U_)
1339 {
1340         draw_tap_listeners(FALSE);
1341         return 1;
1342 }
1343 #else
1344
1345 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1346    use threads all updte_thread_mutex can be dropped and protect/unprotect
1347    would just be empty functions.
1348
1349    This allows gtk2-rpcstat.c and friends to be copied unmodified to
1350    gtk1-wireshark and it will just work.
1351  */
1352 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1353 gpointer
1354 update_thread(gpointer data _U_)
1355 {
1356     while(1){
1357         GTimeVal tv1, tv2;
1358         g_get_current_time(&tv1);
1359         g_static_mutex_lock(&update_thread_mutex);
1360         gdk_threads_enter();
1361         draw_tap_listeners(FALSE);
1362         gdk_threads_leave();
1363         g_static_mutex_unlock(&update_thread_mutex);
1364         g_thread_yield();
1365         g_get_current_time(&tv2);
1366         if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
1367             (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1368             g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
1369                      (tv2.tv_sec * 1000000 + tv2.tv_usec));
1370         }
1371     }
1372     return NULL;
1373 }
1374 #endif
1375 void
1376 protect_thread_critical_region(void)
1377 {
1378 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1379     g_static_mutex_lock(&update_thread_mutex);
1380 #endif
1381 }
1382 void
1383 unprotect_thread_critical_region(void)
1384 {
1385 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1386     g_static_mutex_unlock(&update_thread_mutex);
1387 #endif
1388 }
1389
1390 /* Set the file name in the status line, in the name for the main window,
1391    and in the name for the main window's icon. */
1392 static void
1393 set_display_filename(capture_file *cf)
1394 {
1395   const gchar *name_ptr;
1396   gchar       *status_msg;
1397   gchar       *size_str;
1398   gchar       *win_name;
1399
1400   name_ptr = cf_get_display_name(cf);
1401
1402   if (!cf->is_tempfile && cf->filename) {
1403     /* Add this filename to the list of recent files in the "Recent Files" submenu */
1404     add_menu_recent_capture_file(cf->filename);
1405   }
1406
1407   /* convert file size */
1408   if (cf->f_datalen/1024/1024 > 10) {
1409     size_str = g_strdup_printf("%lld MB", cf->f_datalen/1024/1024);
1410   } else if (cf->f_datalen/1024 > 10) {
1411     size_str = g_strdup_printf("%lld KB", cf->f_datalen/1024);
1412   } else {
1413     size_str = g_strdup_printf("%lld Bytes", cf->f_datalen);
1414   }
1415
1416   /* statusbar */
1417 #if 0
1418   /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1419   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu [Expert: %s]",
1420     (cf->filename) ? cf->filename : "", size_str,
1421     (long)cf->elapsed_time.secs/3600,
1422     (long)cf->elapsed_time.secs%3600/60,
1423     (long)cf->elapsed_time.secs%60,
1424     val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1425 #endif
1426   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
1427     (cf->filename) ? cf->filename : "", size_str,
1428     (long)cf->elapsed_time.secs/3600,
1429     (long)cf->elapsed_time.secs%3600/60,
1430     (long)cf->elapsed_time.secs%60);
1431   g_free(size_str);
1432   statusbar_push_file_msg(status_msg);
1433   g_free(status_msg);
1434
1435   /* window title */
1436   win_name = g_strdup_printf("%s - Wireshark", name_ptr);
1437   set_main_window_name(win_name);
1438   g_free(win_name);
1439 }
1440
1441 GtkWidget           *close_dlg = NULL;
1442
1443 static void
1444 main_cf_cb_file_closing(capture_file *cf)
1445 {
1446
1447     /* if we have more than 10000 packets, show a splash screen while closing */
1448     /* XXX - don't know a better way to decide wether to show or not,
1449      * as most of the time is spend in a single eth_clist_clear function,
1450      * so we can't use a progress bar here! */
1451     if(cf->count > 10000) {
1452         close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1453                                   "%sClosing file!%s\n\nPlease wait ...",
1454                                   simple_dialog_primary_start(),
1455                                   simple_dialog_primary_end());
1456 #if GTK_MAJOR_VERSION >= 2
1457         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1458 #else
1459         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER);
1460 #endif
1461     }
1462
1463     /* Destroy all windows, which refer to the
1464        capture file we're closing. */
1465     destroy_packet_wins();
1466     file_save_as_destroy();
1467
1468     /* Clear any file-related status bar messages.
1469        XXX - should be "clear *ALL* file-related status bar messages;
1470        will there ever be more than one on the stack? */
1471     statusbar_pop_file_msg();
1472
1473     /* Restore the standard title bar message. */
1474     set_main_window_name("The Wireshark Network Analyzer");
1475
1476     /* Disable all menu items that make sense only if you have a capture. */
1477     set_menus_for_capture_file(FALSE);
1478     set_menus_for_unsaved_capture_file(FALSE);
1479     set_menus_for_captured_packets(FALSE);
1480     set_menus_for_selected_packet(cf);
1481     set_menus_for_capture_in_progress(FALSE);
1482     set_menus_for_selected_tree_row(cf);
1483
1484     /* Set up main window for no capture file. */
1485     main_set_for_capture_file(FALSE);
1486
1487     main_window_update();
1488 }
1489
1490 static void
1491 main_cf_cb_file_closed(capture_file *cf _U_)
1492 {
1493   if(close_dlg != NULL) {
1494     splash_destroy(close_dlg);
1495     close_dlg = NULL;
1496   }
1497
1498   /* go back to "No packets" */
1499   packets_bar_update();
1500 }
1501
1502 static void
1503 main_cf_cb_file_read_start(capture_file *cf)
1504 {
1505   const gchar *name_ptr;
1506   gchar       *load_msg;
1507
1508   name_ptr = get_basename(cf->filename);
1509
1510   load_msg = g_strdup_printf(" Loading: %s", name_ptr);
1511   statusbar_push_file_msg(load_msg);
1512   g_free(load_msg);
1513
1514   /* Set up main window for a capture file. */
1515   main_set_for_capture_file(TRUE);
1516 }
1517
1518 static void
1519 main_cf_cb_file_read_finished(capture_file *cf)
1520 {
1521     statusbar_pop_file_msg();
1522     set_display_filename(cf);
1523
1524     /* Enable menu items that make sense if you have a capture file you've
1525      finished reading. */
1526     set_menus_for_capture_file(TRUE);
1527     set_menus_for_unsaved_capture_file(!cf->user_saved);
1528
1529     /* Enable menu items that make sense if you have some captured packets. */
1530     set_menus_for_captured_packets(TRUE);
1531 }
1532
1533 #if GTK_MAJOR_VERSION >= 2
1534 GList *icon_list_create(
1535     const char **icon16_xpm,
1536     const char **icon32_xpm,
1537     const char **icon48_xpm,
1538     const char **icon64_xpm)
1539 {
1540   GList *icon_list = NULL;
1541   GdkPixbuf * pixbuf16;
1542   GdkPixbuf * pixbuf32;
1543   GdkPixbuf * pixbuf48;
1544   GdkPixbuf * pixbuf64;
1545
1546
1547   if(icon16_xpm != NULL) {
1548       pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1549       g_assert(pixbuf16);
1550       icon_list = g_list_append(icon_list, pixbuf16);
1551   }
1552
1553   if(icon32_xpm != NULL) {
1554       pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1555       g_assert(pixbuf32);
1556       icon_list = g_list_append(icon_list, pixbuf32);
1557   }
1558
1559   if(icon48_xpm != NULL) {
1560       pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1561       g_assert(pixbuf48);
1562       icon_list = g_list_append(icon_list, pixbuf48);
1563   }
1564
1565   if(icon64_xpm != NULL) {
1566       pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1567       g_assert(pixbuf64);
1568       icon_list = g_list_append(icon_list, pixbuf64);
1569   }
1570
1571   return icon_list;
1572 }
1573 #endif
1574
1575 #ifdef HAVE_LIBPCAP
1576 static void
1577 main_cf_cb_live_capture_prepared(capture_options *capture_opts)
1578 {
1579     gchar *title;
1580 #if GTK_MAJOR_VERSION >= 2
1581     static GList *icon_list = NULL;
1582 #endif
1583
1584
1585     if(capture_opts->iface) {
1586         title = g_strdup_printf("%s: Capturing - Wireshark",
1587                             get_interface_descriptive_name(capture_opts->iface));
1588     } else {
1589         title = g_strdup_printf("Capturing - Wireshark");
1590     }
1591     set_main_window_name(title);
1592     g_free(title);
1593
1594 #if GTK_MAJOR_VERSION >= 2
1595     if(icon_list == NULL) {
1596         icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1597     }
1598     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1599 #endif
1600
1601     /* Disable menu items that make no sense if you're currently running
1602        a capture. */
1603     set_menus_for_capture_in_progress(TRUE);
1604
1605     /* update statusbar */
1606     statusbar_push_file_msg("Waiting for capture input data ...");
1607
1608     /* Don't set up main window for a capture file. */
1609     main_set_for_capture_file(FALSE);
1610 }
1611
1612 static void
1613 main_cf_cb_live_capture_update_started(capture_options *capture_opts)
1614 {
1615     gchar *capture_msg;
1616     gchar *title;
1617
1618     /* We've done this in "prepared" above, but it will be cleared while
1619        switching to the next multiple file. */
1620     if(capture_opts->iface) {
1621         title = g_strdup_printf("%s: Capturing - Wireshark",
1622                             get_interface_descriptive_name(capture_opts->iface));
1623     } else {
1624         title = g_strdup_printf("Capturing - Wireshark");
1625     }
1626     set_main_window_name(title);
1627     g_free(title);
1628
1629     set_menus_for_capture_in_progress(TRUE);
1630
1631     /* Enable menu items that make sense if you have some captured
1632        packets (yes, I know, we don't have any *yet*). */
1633     set_menus_for_captured_packets(TRUE);
1634
1635     statusbar_pop_file_msg();
1636
1637     if(capture_opts->iface) {
1638         capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1639             get_interface_descriptive_name(capture_opts->iface),
1640             (capture_opts->save_file) ? capture_opts->save_file : "");
1641     } else {
1642         capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
1643             (capture_opts->save_file) ? capture_opts->save_file : "");
1644     }
1645
1646     statusbar_push_file_msg(capture_msg);
1647
1648     g_free(capture_msg);
1649
1650     /* Set up main window for a capture file. */
1651     main_set_for_capture_file(TRUE);
1652 }
1653
1654 static void
1655 main_cf_cb_live_capture_update_continue(capture_file *cf)
1656 {
1657     gchar *capture_msg;
1658
1659
1660     statusbar_pop_file_msg();
1661
1662 #if 0
1663     /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1664     if (cf->f_datalen/1024/1024 > 10) {
1665         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld MB [Expert: %s]",
1666             get_interface_descriptive_name(capture_opts->iface),
1667             capture_opts->save_file,
1668             cf->f_datalen/1024/1024,
1669             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1670     } else if (cf->f_datalen/1024 > 10) {
1671         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld KB [Expert: %s]",
1672             get_interface_descriptive_name(capture_opts->iface),
1673             capture_opts->save_file,
1674             cf->f_datalen/1024,
1675             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1676     } else {
1677         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld Bytes [Expert: %s]",
1678             get_interface_descriptive_name(capture_opts->iface),
1679             capture_opts->save_file,
1680             cf->f_datalen,
1681             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1682     }
1683 #endif
1684     if (cf->f_datalen/1024/1024 > 10) {
1685         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld MB",
1686             get_interface_descriptive_name(capture_opts->iface),
1687             capture_opts->save_file,
1688             cf->f_datalen/1024/1024);
1689     } else if (cf->f_datalen/1024 > 10) {
1690         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld KB",
1691             get_interface_descriptive_name(capture_opts->iface),
1692             capture_opts->save_file,
1693             cf->f_datalen/1024);
1694     } else {
1695         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld Bytes",
1696             get_interface_descriptive_name(capture_opts->iface),
1697             capture_opts->save_file,
1698             cf->f_datalen);
1699     }
1700
1701     statusbar_push_file_msg(capture_msg);
1702 }
1703
1704 GtkWidget * stop_dlg = NULL;
1705
1706 static void
1707 main_cf_cb_live_capture_update_finished(capture_file *cf)
1708 {
1709 #if GTK_MAJOR_VERSION >= 2
1710     static GList *icon_list = NULL;
1711 #endif
1712
1713     if(stop_dlg != NULL) {
1714                 simple_dialog_close(stop_dlg);
1715                 stop_dlg = NULL;
1716         }
1717
1718     /* Pop the "<live capture in progress>" message off the status bar. */
1719     statusbar_pop_file_msg();
1720
1721     set_display_filename(cf);
1722
1723     /* Enable menu items that make sense if you're not currently running
1724      a capture. */
1725     set_menus_for_capture_in_progress(FALSE);
1726
1727     /* Enable menu items that make sense if you have a capture file
1728      you've finished reading. */
1729     set_menus_for_capture_file(TRUE);
1730     set_menus_for_unsaved_capture_file(!cf->user_saved);
1731
1732     /* Set up main window for a capture file. */
1733     main_set_for_capture_file(TRUE);
1734
1735 #if GTK_MAJOR_VERSION >= 2
1736     if(icon_list == NULL) {
1737         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1738     }
1739     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1740 #endif
1741
1742     if(capture_opts->quit_after_cap) {
1743         /* command line asked us to quit after the capture */
1744         /* don't pop up a dialog to ask for unsaved files etc. */
1745         main_do_quit();
1746     }
1747 }
1748
1749 static void
1750 main_cf_cb_live_capture_fixed_started(capture_options *capture_opts)
1751 {
1752     gchar *capture_msg;
1753
1754
1755     /* Enable menu items that make sense if you have some captured
1756        packets (yes, I know, we don't have any *yet*). */
1757     /*set_menus_for_captured_packets(TRUE);*/
1758
1759     statusbar_pop_file_msg();
1760
1761     capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1762         get_interface_descriptive_name(capture_opts->iface),
1763         (capture_opts->save_file) ? capture_opts->save_file : "");
1764
1765     statusbar_push_file_msg(capture_msg);
1766     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " P: 0");
1767
1768     g_free(capture_msg);
1769
1770     /* Don't set up main window for a capture file. */
1771     main_set_for_capture_file(FALSE);
1772 }
1773
1774 static void
1775 main_cf_cb_live_capture_fixed_continue(capture_file *cf)
1776 {
1777     gchar *capture_msg;
1778
1779
1780         gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1781
1782     capture_msg = g_strdup_printf(" P: %u",
1783         cf_get_packet_count(cf));
1784
1785     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
1786
1787     g_free(capture_msg);
1788 }
1789
1790 static void
1791 main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
1792 {
1793 #if GTK_MAJOR_VERSION >= 2
1794     static GList *icon_list = NULL;
1795 #endif
1796
1797     if(stop_dlg != NULL) {
1798                 simple_dialog_close(stop_dlg);
1799                 stop_dlg = NULL;
1800         }
1801
1802     /* Pop the "<live capture in progress>" message off the status bar. */
1803     statusbar_pop_file_msg();
1804
1805     /* Pop the "<capturing>" message off the status bar */
1806         gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1807
1808     /*set_display_filename(cf);*/
1809
1810     /* Enable menu items that make sense if you're not currently running
1811      a capture. */
1812     set_menus_for_capture_in_progress(FALSE);
1813
1814     /* Restore the standard title bar message */
1815     /* (just in case we have trouble opening the capture file). */
1816     set_main_window_name("The Wireshark Network Analyzer");
1817
1818 #if GTK_MAJOR_VERSION >= 2
1819     if(icon_list == NULL) {
1820         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1821     }
1822     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1823 #endif
1824
1825     /* We don't have loaded the capture file, this will be done later.
1826      * For now we still have simply a blank screen. */
1827
1828     if(capture_opts->quit_after_cap) {
1829         /* command line asked us to quit after the capture */
1830         /* don't pop up a dialog to ask for unsaved files etc. */
1831         main_do_quit();
1832     }
1833 }
1834
1835 static void
1836 main_cf_cb_live_capture_stopping(capture_file *cf _U_)
1837 {
1838     /* Beware: this state won't be called, if the capture child
1839      * closes the capturing on it's own! */
1840 #if 0
1841     /* XXX - the time to stop the capture has been reduced (this was only a
1842      * problem on Win32 because of the capture piping), so showing a splash
1843      * isn't really necessary any longer. Unfortunately, the GTKClist packet
1844      * list seems to have problems updating after the dialog is closed, so
1845      * this was disabled here. */
1846     stop_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sCapture stop!%s\n\nPlease wait ...",
1847                 simple_dialog_primary_start(), simple_dialog_primary_end());
1848 #if GTK_MAJOR_VERSION >= 2
1849     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1850 #else
1851     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER);
1852 #endif
1853 #endif
1854 }
1855
1856 #endif
1857
1858 static void
1859 main_cf_cb_packet_selected(gpointer data)
1860 {
1861     capture_file *cf = data;
1862
1863     /* Display the GUI protocol tree and hex dump.
1864       XXX - why do we dump core if we call "proto_tree_draw()"
1865       before calling "add_byte_views()"? */
1866     add_main_byte_views(cf->edt);
1867     main_proto_tree_draw(cf->edt->tree);
1868
1869     /* The user is searching for a string in the data or a hex value,
1870      * highlight the field that is found in the tree and hex displays. */
1871 #if GTK_MAJOR_VERSION < 2
1872     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1873             highlight_field(cf->edt->tvb, cfile.search_pos,
1874                                     (GtkCTree *)tree_view, cf->edt->tree);
1875 #else
1876     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1877             highlight_field(cf->edt->tvb, cfile.search_pos,
1878                                     (GtkTreeView *)tree_view, cf->edt->tree);
1879 #endif
1880                     cfile.search_pos = 0; /* Reset the position */
1881     }
1882
1883     /* A packet is selected. */
1884     set_menus_for_selected_packet(cf);
1885 }
1886
1887 static void
1888 main_cf_cb_packet_unselected(capture_file *cf)
1889 {
1890     /* Clear out the display of that packet. */
1891     clear_tree_and_hex_views();
1892
1893     /* No packet is selected. */
1894     set_menus_for_selected_packet(cf);
1895 }
1896
1897 static void
1898 main_cf_cb_field_unselected(capture_file *cf)
1899 {
1900     statusbar_pop_field_msg();
1901     set_menus_for_selected_tree_row(cf);
1902 }
1903
1904 static void
1905 main_cf_cb_file_safe_started(gchar * filename)
1906 {
1907     const gchar  *name_ptr;
1908     gchar        *save_msg;
1909
1910     name_ptr = get_basename(filename);
1911
1912     save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
1913
1914     statusbar_push_file_msg(save_msg);
1915     g_free(save_msg);
1916 }
1917
1918 static void
1919 main_cf_cb_file_safe_finished(gpointer data _U_)
1920 {
1921     /* Pop the "Saving:" message off the status bar. */
1922     statusbar_pop_file_msg();
1923 }
1924
1925 static void
1926 main_cf_cb_file_safe_failed(gpointer data _U_)
1927 {
1928     /* Pop the "Saving:" message off the status bar. */
1929     statusbar_pop_file_msg();
1930 }
1931
1932 static void
1933 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1934 {
1935     set_menus_for_unsaved_capture_file(FALSE);
1936 }
1937
1938 static void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1939 {
1940     switch(event) {
1941     case(cf_cb_file_closing):
1942         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1943         main_cf_cb_file_closing(data);
1944         break;
1945     case(cf_cb_file_closed):
1946         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1947         main_cf_cb_file_closed(data);
1948         break;
1949     case(cf_cb_file_read_start):
1950         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1951         main_cf_cb_file_read_start(data);
1952         break;
1953     case(cf_cb_file_read_finished):
1954         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1955         main_cf_cb_file_read_finished(data);
1956         break;
1957 #ifdef HAVE_LIBPCAP
1958     case(cf_cb_live_capture_prepared):
1959         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1960         main_cf_cb_live_capture_prepared(data);
1961         break;
1962     case(cf_cb_live_capture_update_started):
1963         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1964         main_cf_cb_live_capture_update_started(data);
1965         break;
1966     case(cf_cb_live_capture_update_continue):
1967         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1968         main_cf_cb_live_capture_update_continue(data);
1969         break;
1970     case(cf_cb_live_capture_update_finished):
1971         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1972         main_cf_cb_live_capture_update_finished(data);
1973         break;
1974     case(cf_cb_live_capture_fixed_started):
1975         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1976         main_cf_cb_live_capture_fixed_started(data);
1977         break;
1978     case(cf_cb_live_capture_fixed_continue):
1979         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");
1980         main_cf_cb_live_capture_fixed_continue(data);
1981         break;
1982     case(cf_cb_live_capture_fixed_finished):
1983         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1984         main_cf_cb_live_capture_fixed_finished(data);
1985         break;
1986     case(cf_cb_live_capture_stopping):
1987         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1988         main_cf_cb_live_capture_stopping(data);
1989         break;
1990 #endif
1991     case(cf_cb_packet_selected):
1992         main_cf_cb_packet_selected(data);
1993         break;
1994     case(cf_cb_packet_unselected):
1995         main_cf_cb_packet_unselected(data);
1996         break;
1997     case(cf_cb_field_unselected):
1998         main_cf_cb_field_unselected(data);
1999         break;
2000     case(cf_cb_file_safe_started):
2001         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
2002         main_cf_cb_file_safe_started(data);
2003         break;
2004     case(cf_cb_file_safe_finished):
2005         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
2006         main_cf_cb_file_safe_finished(data);
2007         break;
2008     case(cf_cb_file_safe_reload_finished):
2009         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
2010         main_cf_cb_file_safe_reload_finished(data);
2011         break;
2012     case(cf_cb_file_safe_failed):
2013         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
2014         main_cf_cb_file_safe_failed(data);
2015         break;
2016     default:
2017         g_warning("main_cf_callback: event %u unknown", event);
2018         g_assert_not_reached();
2019     }
2020 }
2021
2022 static void
2023 get_gui_compiled_info(GString *str)
2024 {
2025   get_epan_compiled_version_info(str);
2026
2027   g_string_append(str, ", ");
2028 #ifdef HAVE_LIBPORTAUDIO
2029 #ifdef PORTAUDIO_API_1
2030   g_string_append(str, "with PortAudio <= V18");
2031 #else /* PORTAUDIO_API_1 */
2032   g_string_append(str, "with PortAudio ");
2033   g_string_append(str, Pa_GetVersionText());
2034 #endif /* PORTAUDIO_API_1 */
2035 #else /* HAVE_LIBPORTAUDIO */
2036   g_string_append(str, "without PortAudio");
2037 #endif /* HAVE_LIBPORTAUDIO */
2038
2039   g_string_append(str, ", ");
2040 #ifdef HAVE_AIRPCAP
2041   get_compiled_airpcap_version(str);
2042 #else
2043   g_string_append(str, "without AirPcap");
2044 #endif
2045 }
2046
2047 static void
2048 get_gui_runtime_info(GString *str
2049 #ifndef HAVE_AIRPCAP
2050         _U_
2051 #endif
2052 )
2053 {
2054 #ifdef HAVE_AIRPCAP
2055   g_string_append(str, ", ");
2056   get_runtime_airpcap_version(str);
2057 #endif
2058 }
2059
2060 /* And now our feature presentation... [ fade to music ] */
2061 int
2062 main(int argc, char *argv[])
2063 {
2064   char                *init_progfile_dir_error;
2065   char                *s;
2066   int                  i;
2067   int                  opt;
2068   extern char         *optarg;
2069   gboolean             arg_error = FALSE;
2070
2071 #ifdef _WIN32
2072   WSADATA              wsaData;
2073 #endif  /* _WIN32 */
2074
2075   char                *rf_path;
2076   int                  rf_open_errno;
2077   char                *gpf_path, *pf_path;
2078   char                *cf_path, *df_path;
2079   char                *gdp_path, *dp_path;
2080   int                  gpf_open_errno, gpf_read_errno;
2081   int                  pf_open_errno, pf_read_errno;
2082   int                  cf_open_errno, df_open_errno;
2083   int                  gdp_open_errno, gdp_read_errno;
2084   int                  dp_open_errno, dp_read_errno;
2085   int                  err;
2086 #ifdef HAVE_LIBPCAP
2087   gboolean             start_capture = FALSE;
2088 #else
2089   gboolean             capture_option_specified = FALSE;
2090 #endif
2091   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2092   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL;
2093   dfilter_t           *rfcode = NULL;
2094   gboolean             rfilter_parse_failed = FALSE;
2095   e_prefs             *prefs;
2096   char                 badopt;
2097   GtkWidget           *splash_win = NULL;
2098   GLogLevelFlags       log_flags;
2099   guint                go_to_packet = 0;
2100   int                  optind_initial;
2101   int                  status;
2102
2103 #ifdef HAVE_AIRPCAP
2104   char                  err_str[AIRPCAP_ERRBUF_SIZE];
2105   gchar                 *cant_get_if_list_errstr;
2106 #endif
2107
2108 #define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:pQr:R:Ss:t:vw:X:y:z:"
2109
2110 #if defined HAVE_LIBPCAP && defined _WIN32
2111 #define OPTSTRING_WIN32 "B:"
2112 #else
2113 #define OPTSTRING_WIN32 ""
2114 #endif
2115
2116   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
2117     OPTSTRING_INIT OPTSTRING_WIN32;
2118
2119   /*
2120    * Attempt to get the pathname of the executable file.
2121    */
2122   init_progfile_dir_error = init_progfile_dir(argv[0]);
2123
2124   /*
2125    * Get credential information for later use.
2126    */
2127   get_credential_info();
2128
2129   /* initialize the funnel mini-api */
2130   initialize_funnel_ops();
2131
2132 #ifdef _WIN32
2133   /* Load wpcap if possible. Do this before collecting the run-time version information */
2134   load_wpcap();
2135
2136   /* ... and also load the packet.dll from wpcap */
2137   wpcap_packet_load();
2138
2139 #ifdef HAVE_AIRPCAP
2140    /* Load the airpcap.dll.  This must also be done before collecting
2141     * run-time version information. */
2142   airpcap_dll_ret_val = load_airpcap();
2143
2144   switch (airpcap_dll_ret_val) {
2145   case AIRPCAP_DLL_OK:
2146     /* load the airpcap interfaces */
2147     airpcap_if_list = get_airpcap_interface_list(&err, err_str);
2148
2149     if (airpcap_if_list == NULL && err == CANT_GET_AIRPCAP_INTERFACE_LIST) {
2150       cant_get_if_list_errstr = cant_get_airpcap_if_list_error_message(err_str);
2151       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", cant_get_if_list_errstr);
2152       g_free(cant_get_if_list_errstr);
2153     }
2154     /* select the first ad default (THIS SHOULD BE CHANGED) */
2155     airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2156     break;
2157
2158 #if 0
2159     /*
2160      * XXX - Maybe we need to warn the user if one of the following happens???
2161      */
2162     case AIRPCAP_DLL_OLD:
2163       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2164       break;
2165
2166     case AIRPCAP_DLL_ERROR:
2167       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2168       break;
2169
2170     case AIRPCAP_DLL_NOT_FOUND:
2171       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2172       break;
2173 #endif
2174   }
2175 #endif /* HAVE_AIRPCAP */
2176
2177   /* Start windows sockets */
2178   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2179 #endif  /* _WIN32 */
2180
2181   /* Assemble the compile-time version information string */
2182   comp_info_str = g_string_new("Compiled ");
2183
2184   g_string_append(comp_info_str, "with ");
2185   g_string_sprintfa(comp_info_str,
2186 #ifdef GTK_MAJOR_VERSION
2187                     "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2188                     GTK_MICRO_VERSION);
2189 #else
2190                     "GTK+ (version unknown)");
2191 #endif
2192   g_string_append(comp_info_str, ", ");
2193
2194   get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2195
2196   /* Assemble the run-time version information string */
2197   runtime_info_str = g_string_new("Running ");
2198   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2199
2200
2201   /* "pre-scan" the command line parameters, if we have "console only"
2202      parameters.  We do this so we don't start GTK+ if we're only showing
2203      command-line help or version information.
2204
2205      XXX - this pre-scan is doen before we start GTK+, so we haven't
2206      run gtk_init() on the arguments.  That means that GTK+ arguments
2207      have not been removed from the argument list; those arguments
2208      begin with "--", and will be treated as an error by getopt().
2209
2210      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2211      error messages. */
2212   opterr = 0;
2213   optind_initial = optind;
2214   while ((opt = getopt(argc, argv, optstring)) != -1) {
2215     switch (opt) {
2216       case 'h':        /* Print help and exit */
2217         print_usage(TRUE);
2218         exit(0);
2219         break;
2220       case 'v':        /* Show version and exit */
2221         show_version();
2222         exit(0);
2223         break;
2224       case 'X':
2225           /*
2226            *  Extension command line options have to be processed before
2227            *  we call epan_init() as they are supposed to be used by dissectors
2228            *  or taps very early in the registration process.
2229            */
2230           ex_opt_add(optarg);
2231           break;
2232       case '?':        /* Ignore errors - the "real" scan will catch them. */
2233         break;
2234     }
2235   }
2236
2237   /* Set getopt index back to initial value, so it will start with the
2238      first command line parameter again.  Also reset opterr to 1, so that
2239      error messages are printed by getopt().
2240
2241      XXX - this seems to work on most platforms, but time will tell.
2242      The Single UNIX Specification says "The getopt() function need
2243      not be reentrant", so this isn't guaranteed to work.  The Mac
2244      OS X 10.4[.x] getopt() man page says
2245
2246        In order to use getopt() to evaluate multiple sets of arguments, or to
2247        evaluate a single set of arguments multiple times, the variable optreset
2248        must be set to 1 before the second and each additional set of calls to
2249        getopt(), and the variable optind must be reinitialized.
2250
2251            ...
2252
2253        The optreset variable was added to make it possible to call the getopt()
2254        function multiple times.  This is an extension to the IEEE Std 1003.2
2255        (``POSIX.2'') specification.
2256
2257      which I think comes from one of the other BSDs.
2258
2259      XXX - if we want to control all the command-line option errors, so
2260      that we can display them where we choose (e.g., in a window), we'd
2261      want to leave opterr as 0, and produce our own messages using optopt.
2262      We'd have to check the value of optopt to see if it's a valid option
2263      letter, in which case *presumably* the error is "this option requires
2264      an argument but none was specified", or not a valid option letter,
2265      in which case *presumably* the error is "this option isn't valid".
2266      Some versions of getopt() let you supply a option string beginning
2267      with ':', which means that getopt() will return ':' rather than '?'
2268      for "this option requires an argument but none was specified", but
2269      not all do. */
2270   optind = optind_initial;
2271   opterr = 1;
2272
2273   /* Set the current locale according to the program environment.
2274    * We haven't localized anything, but some GTK widgets are localized
2275    * (the file selection dialogue, for example).
2276    * This also sets the C-language locale to the native environment. */
2277   gtk_set_locale();
2278
2279   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2280   gtk_init (&argc, &argv);
2281
2282   cf_callback_add(main_cf_callback, NULL);
2283
2284 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
2285   /* initialize our GTK eth_clist_type */
2286   init_eth_clist_type();
2287 #endif
2288
2289   /* Arrange that if we have no console window, and a GLib message logging
2290      routine is called to log a message, we pop up a console window.
2291
2292      We do that by inserting our own handler for all messages logged
2293      to the default domain; that handler pops up a console if necessary,
2294      and then calls the default handler. */
2295
2296   /* We might want to have component specific log levels later ... */
2297
2298   log_flags =
2299                     G_LOG_LEVEL_ERROR|
2300                     G_LOG_LEVEL_CRITICAL|
2301                     G_LOG_LEVEL_WARNING|
2302                     G_LOG_LEVEL_MESSAGE|
2303                     G_LOG_LEVEL_INFO|
2304                     G_LOG_LEVEL_DEBUG|
2305                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2306
2307   g_log_set_handler(NULL,
2308                     log_flags,
2309                     console_log_handler, NULL /* user_data */);
2310   g_log_set_handler(LOG_DOMAIN_MAIN,
2311                     log_flags,
2312                     console_log_handler, NULL /* user_data */);
2313
2314 #ifdef HAVE_LIBPCAP
2315   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2316                     log_flags,
2317                     console_log_handler, NULL /* user_data */);
2318   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2319                     log_flags,
2320                     console_log_handler, NULL /* user_data */);
2321
2322   /* Set the initial values in the capture_opts. This might be overwritten
2323      by preference settings and then again by the command line parameters. */
2324   capture_opts_init(capture_opts, &cfile);
2325
2326   capture_opts->snaplen             = MIN_PACKET_SIZE;
2327   capture_opts->has_ring_num_files  = TRUE;
2328 #endif
2329
2330   /* We won't come till here, if we had a "console only" command line parameter. */
2331   splash_win = splash_new("Loading Wireshark ...");
2332   if (init_progfile_dir_error != NULL) {
2333     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2334         "Can't get pathname of Wireshark: %s.\n"
2335         "It won't be possible to capture traffic.\n"
2336         "Report this to the Wireshark developers.",
2337         init_progfile_dir_error);
2338     g_free(init_progfile_dir_error);
2339   }
2340
2341   splash_update(splash_win, "Init dissectors ...");
2342
2343   /* Register all dissectors; we must do this before checking for the
2344      "-G" flag, as the "-G" flag dumps information registered by the
2345      dissectors, and we must do it before we read the preferences, in
2346      case any dissectors register preferences. */
2347   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
2348             failure_alert_box,open_failure_alert_box,read_failure_alert_box);
2349
2350   splash_update(splash_win, "Init tap listeners ...");
2351
2352   /* Register all tap listeners; we do this before we parse the arguments,
2353      as the "-z" argument can specify a registered tap. */
2354
2355   /* we register the plugin taps before the other taps because
2356           stats_tree taps plugins will be registered as tap listeners
2357           by stats_tree_stat.c and need to registered before that */
2358
2359 #ifdef HAVE_PLUGINS
2360   register_all_plugin_tap_listeners();
2361 #endif
2362
2363   register_all_tap_listeners();
2364
2365   splash_update(splash_win, "Loading module preferences ...");
2366
2367   /* Now register the preferences for any non-dissector modules.
2368      We must do that before we read the preferences as well. */
2369   prefs_register_modules();
2370
2371   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2372 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
2373   {
2374       GThread *ut;
2375       g_thread_init(NULL);
2376       gdk_threads_init();
2377       ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2378       g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2379   }
2380 #else  /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
2381   /* this is to keep tap extensions updating once every 3 seconds */
2382   gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
2383 #endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
2384
2385 #if HAVE_GNU_ADNS
2386   gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
2387 #endif
2388
2389   splash_update(splash_win, "Loading configuration files ...");
2390
2391   /* Read the preference files. */
2392   prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2393                      &pf_open_errno, &pf_read_errno, &pf_path);
2394
2395   if (gpf_path != NULL) {
2396     if (gpf_open_errno != 0) {
2397       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2398         "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2399         strerror(gpf_open_errno));
2400     }
2401     if (gpf_read_errno != 0) {
2402       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2403         "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2404         strerror(gpf_read_errno));
2405     }
2406   }
2407   if (pf_path != NULL) {
2408     if (pf_open_errno != 0) {
2409       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2410         "Could not open your preferences file\n\"%s\": %s.", pf_path,
2411         strerror(pf_open_errno));
2412     }
2413     if (pf_read_errno != 0) {
2414       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2415         "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2416         strerror(pf_read_errno));
2417     }
2418     g_free(pf_path);
2419     pf_path = NULL;
2420   }
2421
2422 #ifdef _WIN32
2423   /* if the user wants a console to be always there, well, we should open one for him */
2424   if (prefs->gui_console_open == console_open_always) {
2425     create_console();
2426   }
2427 #endif
2428
2429   /* Fill in capture options with values from the preferences */
2430   prefs_to_capture_opts();
2431
2432   /* Read the capture filter file. */
2433   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2434   if (cf_path != NULL) {
2435       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2436         "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2437         strerror(cf_open_errno));
2438       g_free(cf_path);
2439   }
2440
2441   /* Read the display filter file. */
2442   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2443   if (df_path != NULL) {
2444       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2445         "Could not open your display filter file\n\"%s\": %s.", df_path,
2446         strerror(df_open_errno));
2447       g_free(df_path);
2448   }
2449
2450   /* Read the disabled protocols file. */
2451   read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
2452                             &dp_path, &dp_open_errno, &dp_read_errno);
2453   if (gdp_path != NULL) {
2454     if (gdp_open_errno != 0) {
2455       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2456         "Could not open global disabled protocols file\n\"%s\": %s.",
2457         gdp_path, strerror(gdp_open_errno));
2458     }
2459     if (gdp_read_errno != 0) {
2460       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2461         "I/O error reading global disabled protocols file\n\"%s\": %s.",
2462         gdp_path, strerror(gdp_read_errno));
2463     }
2464     g_free(gdp_path);
2465   }
2466   if (dp_path != NULL) {
2467     if (dp_open_errno != 0) {
2468       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2469         "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
2470         strerror(dp_open_errno));
2471     }
2472     if (dp_read_errno != 0) {
2473       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2474         "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
2475         strerror(dp_read_errno));
2476     }
2477     g_free(dp_path);
2478   }
2479
2480   /* Read the (static part) of the recent file. Only the static part of it will be read, */
2481   /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
2482   /* We have to do this already here, so command line parameters can overwrite these values. */
2483   recent_read_static(&rf_path, &rf_open_errno);
2484
2485   init_cap_file(&cfile);
2486
2487   /* Now get our args */
2488   while ((opt = getopt(argc, argv, optstring)) != -1) {
2489     switch (opt) {
2490       /*** capture option specific ***/
2491       case 'a':        /* autostop criteria */
2492       case 'b':        /* Ringbuffer option */
2493       case 'c':        /* Capture xxx packets */
2494       case 'f':        /* capture filter */
2495       case 'k':        /* Start capture immediately */
2496       case 'H':        /* Hide capture info dialog box */
2497       case 'i':        /* Use interface xxx */
2498       case 'p':        /* Don't capture in promiscuous mode */
2499       case 'Q':        /* Quit after capture (just capture to file) */
2500       case 's':        /* Set the snapshot (capture) length */
2501       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2502       case 'w':        /* Write to capture file xxx */
2503       case 'y':        /* Set the pcap data link type */
2504 #ifdef _WIN32
2505       case 'B':        /* Buffer size */
2506 #endif /* _WIN32 */
2507 #ifdef HAVE_LIBPCAP
2508         status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
2509         if(status != 0) {
2510             exit(status);
2511         }
2512 #else
2513         capture_option_specified = TRUE;
2514         arg_error = TRUE;
2515 #endif
2516         break;
2517
2518       /*** all non capture option specific ***/
2519       case 'D':        /* Print a list of capture devices and exit */
2520 #ifdef HAVE_LIBPCAP
2521         capture_opts_list_interfaces();
2522         exit(0);
2523 #else
2524         capture_option_specified = TRUE;
2525         arg_error = TRUE;
2526 #endif
2527         break;
2528       case 'g':        /* Go to packet */
2529         go_to_packet = get_positive_int(optarg, "go to packet");
2530         break;
2531       case 'l':        /* Automatic scrolling in live capture mode */
2532 #ifdef HAVE_LIBPCAP
2533         auto_scroll_live = TRUE;
2534 #else
2535         capture_option_specified = TRUE;
2536         arg_error = TRUE;
2537 #endif
2538         break;
2539       case 'L':        /* Print list of link-layer types and exit */
2540 #ifdef HAVE_LIBPCAP
2541         list_link_layer_types = TRUE;
2542 #else
2543         capture_option_specified = TRUE;
2544         arg_error = TRUE;
2545 #endif
2546         break;
2547       case 'm':        /* Fixed-width font for the display */
2548         if (prefs->PREFS_GUI_FONT_NAME != NULL)
2549           g_free(prefs->PREFS_GUI_FONT_NAME);
2550         prefs->PREFS_GUI_FONT_NAME = g_strdup(optarg);
2551         break;
2552       case 'n':        /* No name resolution */
2553         g_resolv_flags = RESOLV_NONE;
2554         break;
2555       case 'N':        /* Select what types of addresses/port #s to resolve */
2556         if (g_resolv_flags == RESOLV_ALL)
2557           g_resolv_flags = RESOLV_NONE;
2558         badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2559         if (badopt != '\0') {
2560           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2561                         badopt);
2562           exit(1);
2563         }
2564         break;
2565       case 'o':        /* Override preference from command line */
2566         switch (prefs_set_pref(optarg)) {
2567         case PREFS_SET_OK:
2568           break;
2569         case PREFS_SET_SYNTAX_ERR:
2570           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2571           exit(1);
2572           break;
2573         case PREFS_SET_NO_SUCH_PREF:
2574           /* not a preference, might be a recent setting */
2575           switch (recent_set_arg(optarg)) {
2576             case PREFS_SET_OK:
2577               break;
2578             case PREFS_SET_SYNTAX_ERR:
2579               /* shouldn't happen, checked already above */
2580               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2581               exit(1);
2582               break;
2583             case PREFS_SET_NO_SUCH_PREF:
2584             case PREFS_SET_OBSOLETE:
2585               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2586                     optarg);
2587               exit(1);
2588               break;
2589             default:
2590               g_assert_not_reached();
2591             }
2592           break;
2593         case PREFS_SET_OBSOLETE:
2594           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2595                         optarg);
2596           exit(1);
2597           break;
2598         default:
2599           g_assert_not_reached();
2600         }
2601         break;
2602       case 'r':        /* Read capture file xxx */
2603         /* We may set "last_open_dir" to "cf_name", and if we change
2604            "last_open_dir" later, we free the old value, so we have to
2605            set "cf_name" to something that's been allocated. */
2606 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2607         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2608         cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2609 #else
2610         cf_name = g_strdup(optarg);
2611 #endif
2612         break;
2613       case 'R':        /* Read file filter */
2614         rfilter = optarg;
2615         break;
2616       case 't':        /* Time stamp type */
2617         if (strcmp(optarg, "r") == 0)
2618           timestamp_set_type(TS_RELATIVE);
2619         else if (strcmp(optarg, "a") == 0)
2620           timestamp_set_type(TS_ABSOLUTE);
2621         else if (strcmp(optarg, "ad") == 0)
2622           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2623         else if (strcmp(optarg, "d") == 0)
2624           timestamp_set_type(TS_DELTA);
2625         else {
2626           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2627           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2628           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2629           exit(1);
2630         }
2631         break;
2632       case 'X':
2633           /* ext ops were already processed just ignore them this time*/
2634           break;
2635       case 'z':
2636         /* We won't call the init function for the stat this soon
2637            as it would disallow MATE's fields (which are registered
2638            by the preferences set callback) from being used as
2639            part of a tap filter.  Instead, we just add the argument
2640            to a list of stat arguments. */
2641         if (!process_stat_cmd_arg(optarg)) {
2642           cmdarg_err("Invalid -z argument.");
2643           cmdarg_err_cont("  -z argument must be one of :");
2644           list_stat_cmd_args();
2645           exit(1);
2646         }
2647         break;
2648       default:
2649       case '?':        /* Bad flag - print usage message */
2650         arg_error = TRUE;
2651         break;
2652     }
2653   }
2654   argc -= optind;
2655   argv += optind;
2656   if (argc >= 1) {
2657     if (cf_name != NULL) {
2658       /*
2659        * Input file name specified with "-r" *and* specified as a regular
2660        * command-line argument.
2661        */
2662       cmdarg_err("File name specified both with -r and regular argument");
2663       arg_error = TRUE;
2664     } else {
2665       /*
2666        * Input file name not specified with "-r", and a command-line argument
2667        * was specified; treat it as the input file name.
2668        *
2669        * Yes, this is different from tshark, where non-flag command-line
2670        * arguments are a filter, but this works better on GUI desktops
2671        * where a command can be specified to be run to open a particular
2672        * file - yes, you could have "-r" as the last part of the command,
2673        * but that's a bit ugly.
2674        */
2675 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2676       /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2677       cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2678 #else
2679       cf_name = g_strdup(argv[0]);
2680 #endif
2681     }
2682     argc--;
2683     argv++;
2684   }
2685
2686
2687
2688   if (argc != 0) {
2689     /*
2690      * Extra command line arguments were specified; complain.
2691      */
2692     cmdarg_err("Invalid argument: %s", argv[0]);
2693     arg_error = TRUE;
2694   }
2695
2696   if (arg_error) {
2697 #ifndef HAVE_LIBPCAP
2698     if (capture_option_specified) {
2699       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2700     }
2701 #endif
2702     print_usage(FALSE);
2703     exit(1);
2704   }
2705
2706 #ifdef HAVE_LIBPCAP
2707   if (start_capture && list_link_layer_types) {
2708     /* Specifying *both* is bogus. */
2709     cmdarg_err("You can't specify both -L and a live capture.");
2710     exit(1);
2711   }
2712
2713   if (list_link_layer_types) {
2714     /* We're supposed to list the link-layer types for an interface;
2715        did the user also specify a capture file to be read? */
2716     if (cf_name) {
2717       /* Yes - that's bogus. */
2718       cmdarg_err("You can't specify -L and a capture file to be read.");
2719       exit(1);
2720     }
2721     /* No - did they specify a ring buffer option? */
2722     if (capture_opts->multi_files_on) {
2723       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2724       exit(1);
2725     }
2726   } else {
2727     /* We're supposed to do a live capture; did the user also specify
2728        a capture file to be read? */
2729     if (start_capture && cf_name) {
2730       /* Yes - that's bogus. */
2731       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2732       exit(1);
2733     }
2734
2735     /* No - was the ring buffer option specified and, if so, does it make
2736        sense? */
2737     if (capture_opts->multi_files_on) {
2738       /* Ring buffer works only under certain conditions:
2739          a) ring buffer does not work with temporary files;
2740          b) real_time_mode and multi_files_on are mutually exclusive -
2741             real_time_mode takes precedence;
2742          c) it makes no sense to enable the ring buffer if the maximum
2743             file size is set to "infinite". */
2744       if (capture_opts->save_file == NULL) {
2745         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2746         capture_opts->multi_files_on = FALSE;
2747       }
2748 /*      if (capture_opts->real_time_mode) {
2749         cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2750         capture_opts->multi_files_on = FALSE;
2751       }*/
2752       if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
2753         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2754 /* XXX - this must be redesigned as the conditions changed */
2755 /*      capture_opts->multi_files_on = FALSE;*/
2756       }
2757     }
2758   }
2759
2760   if (start_capture || list_link_layer_types) {
2761     /* Did the user specify an interface to use? */
2762     if (!capture_opts_trim_iface(capture_opts,
2763         (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2764         exit(2);
2765     }
2766   }
2767
2768   if (list_link_layer_types) {
2769     status = capture_opts_list_link_layer_types(capture_opts);
2770     exit(status);
2771   }
2772
2773   capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
2774   capture_opts_trim_ring_num_files(capture_opts);
2775 #endif /* HAVE_LIBPCAP */
2776
2777   /* Notify all registered modules that have had any of their preferences
2778      changed either from one of the preferences file or from the command
2779      line that their preferences have changed. */
2780   prefs_apply_all();
2781
2782   /* disabled protocols as per configuration file */
2783   if (gdp_path == NULL && dp_path == NULL) {
2784     set_disabled_protos_list();
2785   }
2786
2787   /* Build the column format array */
2788   col_setup(&cfile.cinfo, prefs->num_cols);
2789   for (i = 0; i < cfile.cinfo.num_cols; i++) {
2790     cfile.cinfo.col_fmt[i] = get_column_format(i);
2791     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
2792     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
2793       NUM_COL_FMTS);
2794     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
2795     cfile.cinfo.col_data[i] = NULL;
2796     if (cfile.cinfo.col_fmt[i] == COL_INFO)
2797       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
2798     else
2799       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2800     cfile.cinfo.col_fence[i] = 0;
2801     cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2802     cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2803   }
2804
2805   for (i = 0; i < cfile.cinfo.num_cols; i++) {
2806       int j;
2807
2808       for (j = 0; j < NUM_COL_FMTS; j++) {
2809          if (!cfile.cinfo.fmt_matx[i][j])
2810              continue;
2811
2812          if (cfile.cinfo.col_first[j] == -1)
2813              cfile.cinfo.col_first[j] = i;
2814          cfile.cinfo.col_last[j] = i;
2815       }
2816   }
2817
2818   /* read in rc file from global and personal configuration paths. */
2819   rc_file = get_datafile_path(RC_FILE);
2820   gtk_rc_parse(rc_file);
2821   rc_file = get_persconffile_path(RC_FILE, FALSE);
2822   gtk_rc_parse(rc_file);
2823
2824   font_init();
2825
2826   /* close the splash screen, as we are going to open the main window now */
2827   splash_destroy(splash_win);
2828
2829   /************************************************************************/
2830   /* Everything is prepared now, preferences and command line was read in */
2831
2832   /* Pop up the main window. */
2833   create_main_window(pl_size, tv_size, bv_size, prefs);
2834
2835   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2836   recent_read_dynamic(&rf_path, &rf_open_errno);
2837   color_filters_enable(recent.packet_list_colorize);
2838
2839   /* rearrange all the widgets as we now have all recent settings ready for this */
2840   main_widgets_rearrange();
2841
2842   /* Fill in column titles.  This must be done after the top level window
2843      is displayed.
2844
2845      XXX - is that still true, with fixed-width columns? */
2846   packet_list_set_column_titles();
2847
2848   menu_recent_read_finished();
2849
2850   switch (user_font_apply()) {
2851   case FA_SUCCESS:
2852       break;
2853   case FA_FONT_NOT_RESIZEABLE:
2854       /* "user_font_apply()" popped up an alert box. */
2855       /* turn off zooming - font can't be resized */
2856   case FA_FONT_NOT_AVAILABLE:
2857       /* XXX - did we successfully load the un-zoomed version earlier?
2858       If so, this *probably* means the font is available, but not at
2859       this particular zoom level, but perhaps some other failure
2860       occurred; I'm not sure you can determine which is the case,
2861       however. */
2862       /* turn off zooming - zoom level is unavailable */
2863   default:
2864       /* in any other case than FA_SUCCESS, turn off zooming */
2865       recent.gui_zoom_level = 0;
2866       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2867   }
2868
2869   dnd_init(top_level);
2870
2871   colors_init();
2872   color_filters_init();
2873   decode_as_init();
2874
2875   /* the window can be sized only, if it's not already shown, so do it now! */
2876   main_load_window_geometry(top_level);
2877
2878   /* If we were given the name of a capture file, read it in now;
2879      we defer it until now, so that, if we can't open it, and pop
2880      up an alert box, the alert box is more likely to come up on
2881      top of the main window - but before the preference-file-error
2882      alert box, so, if we get one of those, it's more likely to come
2883      up on top of us. */
2884   if (cf_name) {
2885     show_main_window(TRUE);
2886     if (rfilter != NULL) {
2887       if (!dfilter_compile(rfilter, &rfcode)) {
2888         bad_dfilter_alert_box(rfilter);
2889         rfilter_parse_failed = TRUE;
2890       }
2891     }
2892     if (!rfilter_parse_failed) {
2893       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2894         /* "cf_open()" succeeded, so it closed the previous
2895            capture file, and thus destroyed any previous read filter
2896            attached to "cf". */
2897
2898         cfile.rfcode = rfcode;
2899         /* Open stat windows; we do so after creating the main window,
2900            to avoid GTK warnings, and after successfully opening the
2901            capture file, so we know we have something to compute stats
2902            on, and after registering all dissectors, so that MATE will
2903            have registered its field array and we can have a tap filter
2904            with one of MATE's late-registered fields as part of the
2905            filter. */
2906         start_requested_stats();
2907
2908         /* Read the capture file. */
2909         switch (cf_read(&cfile)) {
2910
2911         case CF_READ_OK:
2912         case CF_READ_ERROR:
2913           /* Just because we got an error, that doesn't mean we were unable
2914              to read any of the file; we handle what we could get from the
2915              file. */
2916           /* if the user told us to jump to a specific packet, do it now */
2917           if(go_to_packet != 0) {
2918             cf_goto_frame(&cfile, go_to_packet);
2919           }
2920           break;
2921
2922         case CF_READ_ABORTED:
2923           /* Exit now. */
2924           gtk_exit(0);
2925           break;
2926         }
2927         /* Save the name of the containing directory specified in the
2928            path name, if any; we can write over cf_name, which is a
2929            good thing, given that "get_dirname()" does write over its
2930            argument. */
2931         s = get_dirname(cf_name);
2932         /* we might already set this from the recent file, don't overwrite this */
2933         if(get_last_open_dir() == NULL)
2934           set_last_open_dir(s);
2935         g_free(cf_name);
2936         cf_name = NULL;
2937       } else {
2938         if (rfcode != NULL)
2939           dfilter_free(rfcode);
2940         cfile.rfcode = NULL;
2941     show_main_window(FALSE);
2942         set_menus_for_capture_in_progress(FALSE);
2943       }
2944     }
2945   } else {
2946 #ifdef HAVE_LIBPCAP
2947     if (start_capture) {
2948       if (capture_opts->save_file != NULL) {
2949         /* Save the directory name for future file dialogs. */
2950         /* (get_dirname overwrites filename) */
2951         s = get_dirname(g_strdup(capture_opts->save_file));
2952         set_last_open_dir(s);
2953         g_free(s);
2954       }
2955       /* "-k" was specified; start a capture. */
2956       show_main_window(TRUE);
2957       if (capture_start(capture_opts)) {
2958         /* The capture started.  Open stat windows; we do so after creating
2959            the main window, to avoid GTK warnings, and after successfully
2960            opening the capture file, so we know we have something to compute
2961            stats on, and after registering all dissectors, so that MATE will
2962            have registered its field array and we can have a tap filter with
2963            one of MATE's late-registered fields as part of the filter. */
2964         start_requested_stats();
2965       }
2966     }
2967     else {
2968       show_main_window(FALSE);
2969       set_menus_for_capture_in_progress(FALSE);
2970     }
2971
2972     /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2973     if (!start_capture && strlen(capture_opts->cfilter) == 0) {
2974       g_free(capture_opts->cfilter);
2975       capture_opts->cfilter = g_strdup(get_conn_cfilter());
2976     }
2977 #else /* HAVE_LIBPCAP */
2978     show_main_window(FALSE);
2979     set_menus_for_capture_in_progress(FALSE);
2980 #endif /* HAVE_LIBPCAP */
2981   }
2982
2983   /* register our pid if we are being run from a U3 device */
2984   u3_register_pid();
2985
2986   /* we'll enter the GTK loop now and hand the control over to GTK ... */
2987   gtk_main();
2988   /* ... back from GTK, we're going down now! */
2989
2990   /* deregister our pid */
2991   u3_deregister_pid();
2992
2993   epan_cleanup();
2994   g_free(rc_file);
2995
2996 #ifdef _WIN32
2997   /* hide the (unresponsive) main window, while asking the user to close the console window */
2998   gtk_widget_hide(top_level);
2999
3000   /* Shutdown windows sockets */
3001   WSACleanup();
3002
3003   /* For some unknown reason, the "atexit()" call in "create_console()"
3004      doesn't arrange that "destroy_console()" be called when we exit,
3005      so we call it here if a console was created. */
3006   destroy_console();
3007 #endif
3008
3009   gtk_exit(0);
3010
3011   /* This isn't reached, but we need it to keep GCC from complaining
3012      that "main()" returns without returning a value - it knows that
3013      "exit()" never returns, but it doesn't know that "gtk_exit()"
3014      doesn't, as GTK+ doesn't declare it with the attribute
3015      "noreturn". */
3016   return 0;     /* not reached */
3017 }
3018
3019 #ifdef _WIN32
3020
3021 /* We build this as a GUI subsystem application on Win32, so
3022    "WinMain()", not "main()", gets called.
3023
3024    Hack shamelessly stolen from the Win32 port of the GIMP. */
3025 #ifdef __GNUC__
3026 #define _stdcall  __attribute__((stdcall))
3027 #endif
3028
3029 int _stdcall
3030 WinMain (struct HINSTANCE__ *hInstance,
3031          struct HINSTANCE__ *hPrevInstance,
3032          char               *lpszCmdLine,
3033          int                 nCmdShow)
3034 {
3035 #if GTK_MAJOR_VERSION >= 2
3036   INITCOMMONCONTROLSEX comm_ctrl;
3037
3038   /* Initialize our controls. Required for native Windows file dialogs. */
3039   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3040   comm_ctrl.dwSize = sizeof(comm_ctrl);
3041   /* Includes the animate, header, hot key, list view, progress bar,
3042    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3043    * up-down controls
3044    */
3045   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3046   InitCommonControlsEx(&comm_ctrl);
3047
3048   /* RichEd20.DLL is needed for filter entries. */
3049   LoadLibrary(_T("riched20.dll"));
3050 #endif /* GTK_MAJOR_VERSION >= 2 */
3051
3052   has_console = FALSE;
3053   return main (__argc, __argv);
3054 }
3055
3056 /*
3057  * If this application has no console window to which its standard output
3058  * would go, create one.
3059  */
3060 void
3061 create_console(void)
3062 {
3063   if (!has_console) {
3064     /* We have no console to which to print the version string, so
3065        create one and make it the standard input, output, and error. */
3066     if (!AllocConsole())
3067       return;   /* couldn't create console */
3068     eth_freopen("CONIN$", "r", stdin);
3069     eth_freopen("CONOUT$", "w", stdout);
3070     eth_freopen("CONOUT$", "w", stderr);
3071
3072     /* Well, we have a console now. */
3073     has_console = TRUE;
3074
3075     /* Now register "destroy_console()" as a routine to be called just
3076        before the application exits, so that we can destroy the console
3077        after the user has typed a key (so that the console doesn't just
3078        disappear out from under them, giving the user no chance to see
3079        the message(s) we put in there). */
3080     atexit(destroy_console);
3081
3082     SetConsoleTitle(_T("Wireshark Debug Console"));
3083   }
3084 }
3085
3086 static void
3087 destroy_console(void)
3088 {
3089   if (has_console) {
3090     printf("\n\nPress any key to exit\n");
3091     _getch();
3092     FreeConsole();
3093   }
3094 }
3095 #endif /* _WIN32 */
3096
3097
3098 /* This routine should not be necessary, at least as I read the GLib
3099    source code, as it looks as if GLib is, on Win32, *supposed* to
3100    create a console window into which to display its output.
3101
3102    That doesn't happen, however.  I suspect there's something completely
3103    broken about that code in GLib-for-Win32, and that it may be related
3104    to the breakage that forces us to just call "printf()" on the message
3105    rather than passing the message on to "g_log_default_handler()"
3106    (which is the routine that does the aforementioned non-functional
3107    console window creation). */
3108 static void
3109 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3110                     const char *message, gpointer user_data _U_)
3111 {
3112   time_t curr;
3113   struct tm *today;
3114   const char *level;
3115
3116
3117   /* ignore log message, if log_level isn't interesting.
3118      If preferences aren't loaded yet, display message anyway */
3119   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3120      prefs.console_log_level != 0) {
3121     return;
3122   }
3123
3124   /* create a "timestamp" */
3125   time(&curr);
3126   today = localtime(&curr);
3127
3128 #ifdef _WIN32
3129   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3130     /* the user wants a console or the application will terminate immediately */
3131     create_console();
3132   }
3133   if (has_console) {
3134     /* For some unknown reason, the above doesn't appear to actually cause
3135        anything to be sent to the standard output, so we'll just splat the
3136        message out directly, just to make sure it gets out. */
3137 #endif
3138     switch(log_level & G_LOG_LEVEL_MASK) {
3139     case G_LOG_LEVEL_ERROR:
3140         level = "Err ";
3141         break;
3142     case G_LOG_LEVEL_CRITICAL:
3143         level = "Crit";
3144         break;
3145     case G_LOG_LEVEL_WARNING:
3146         level = "Warn";
3147         break;
3148     case G_LOG_LEVEL_MESSAGE:
3149         level = "Msg ";
3150         break;
3151     case G_LOG_LEVEL_INFO:
3152         level = "Info";
3153         break;
3154     case G_LOG_LEVEL_DEBUG:
3155         level = "Dbg ";
3156         break;
3157     default:
3158         fprintf(stderr, "unknown log_level %u\n", log_level);
3159         level = NULL;
3160         g_assert_not_reached();
3161     }
3162
3163     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3164             today->tm_hour, today->tm_min, today->tm_sec,
3165             log_domain != NULL ? log_domain : "",
3166             level, message);
3167 #ifdef _WIN32
3168     if(log_level & G_LOG_LEVEL_ERROR) {
3169         /* wait for a key press before the following error handler will terminate the program
3170            this way the user at least can read the error message */
3171         printf("\n\nPress any key to exit\n");
3172         _getch();
3173     }
3174   } else {
3175     g_log_default_handler(log_domain, log_level, message, user_data);
3176   }
3177 #endif
3178 }
3179
3180
3181 static GtkWidget *info_bar_new(void)
3182 {
3183     /* tip: tooltips don't work on statusbars! */
3184     info_bar = gtk_statusbar_new();
3185     main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
3186     file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
3187     help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
3188 #if GTK_MAJOR_VERSION >= 2
3189     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
3190 #endif
3191     gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
3192
3193     return info_bar;
3194 }
3195
3196 static GtkWidget *packets_bar_new(void)
3197 {
3198     /* tip: tooltips don't work on statusbars! */
3199     packets_bar = gtk_statusbar_new();
3200     packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
3201     packets_bar_update();
3202
3203     return packets_bar;
3204 }
3205
3206
3207 /*
3208  * Helper for main_widgets_rearrange()
3209  */
3210 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3211     gtk_container_remove(GTK_CONTAINER(data), widget);
3212 }
3213
3214 static GtkWidget *main_widget_layout(gint layout_content)
3215 {
3216     switch(layout_content) {
3217     case(layout_pane_content_none):
3218         return NULL;
3219         break;
3220     case(layout_pane_content_plist):
3221         return pkt_scrollw;
3222         break;
3223     case(layout_pane_content_pdetails):
3224         return tv_scrollw;
3225         break;
3226     case(layout_pane_content_pbytes):
3227         return byte_nb_ptr;
3228         break;
3229     default:
3230         g_assert_not_reached();
3231         return NULL;
3232     }
3233 }
3234
3235
3236 /*
3237  * Rearrange the main window widgets
3238  */
3239 void main_widgets_rearrange(void) {
3240     GtkWidget *first_pane_widget1, *first_pane_widget2;
3241     GtkWidget *second_pane_widget1, *second_pane_widget2;
3242     gboolean split_top_left;
3243
3244     /* be a bit faster */
3245     gtk_widget_hide(main_vbox);
3246
3247     /* be sure, we don't loose a widget while rearranging */
3248     gtk_widget_ref(menubar);
3249     gtk_widget_ref(main_tb);
3250     gtk_widget_ref(filter_tb);
3251
3252 #ifdef HAVE_AIRPCAP
3253     gtk_widget_ref(airpcap_tb);
3254 #endif
3255
3256     gtk_widget_ref(pkt_scrollw);
3257     gtk_widget_ref(tv_scrollw);
3258     gtk_widget_ref(byte_nb_ptr);
3259     gtk_widget_ref(stat_hbox);
3260     gtk_widget_ref(info_bar);
3261     gtk_widget_ref(packets_bar);
3262     gtk_widget_ref(status_pane);
3263     gtk_widget_ref(main_pane_v1);
3264     gtk_widget_ref(main_pane_v2);
3265     gtk_widget_ref(main_pane_h1);
3266     gtk_widget_ref(main_pane_h2);
3267     gtk_widget_ref(welcome_pane);
3268
3269     /* empty all containers participating */
3270     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3271     gtk_container_foreach(GTK_CONTAINER(stat_hbox),     foreach_remove_a_child, stat_hbox);
3272     gtk_container_foreach(GTK_CONTAINER(status_pane),   foreach_remove_a_child, status_pane);
3273     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3274     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3275     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3276     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3277
3278     /* add the menubar always at the top */
3279     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3280
3281     /* main toolbar */
3282     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3283
3284     /* filter toolbar in toolbar area */
3285     if (!prefs.filter_toolbar_show_in_statusbar) {
3286         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3287     }
3288
3289 #ifdef HAVE_AIRPCAP
3290     /* airpcap toolbar */
3291     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3292 #endif
3293
3294     /* fill the main layout panes */
3295     switch(prefs.gui_layout_type) {
3296     case(layout_type_5):
3297         main_first_pane  = main_pane_v1;
3298         main_second_pane = main_pane_v2;
3299         split_top_left = FALSE;
3300         break;
3301     case(layout_type_2):
3302         main_first_pane  = main_pane_v1;
3303         main_second_pane = main_pane_h1;
3304         split_top_left = FALSE;
3305         break;
3306     case(layout_type_1):
3307         main_first_pane  = main_pane_v1;
3308         main_second_pane = main_pane_h1;
3309         split_top_left = TRUE;
3310         break;
3311     case(layout_type_4):
3312         main_first_pane  = main_pane_h1;
3313         main_second_pane = main_pane_v1;
3314         split_top_left = FALSE;
3315         break;
3316     case(layout_type_3):
3317         main_first_pane  = main_pane_h1;
3318         main_second_pane = main_pane_v1;
3319         split_top_left = TRUE;
3320         break;
3321     case(layout_type_6):
3322         main_first_pane  = main_pane_h1;
3323         main_second_pane = main_pane_h2;
3324         split_top_left = FALSE;
3325         break;
3326     default:
3327         main_first_pane = NULL;
3328         main_second_pane = NULL;
3329         split_top_left = FALSE;
3330         g_assert_not_reached();
3331     }
3332     if (split_top_left) {
3333         first_pane_widget1 = main_second_pane;
3334         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3335         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3336         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3337     } else {
3338         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3339         first_pane_widget2 = main_second_pane;
3340         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3341         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3342     }
3343     if (first_pane_widget1 != NULL)
3344         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3345     if (first_pane_widget2 != NULL)
3346         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3347     if (second_pane_widget1 != NULL)
3348         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3349     if (second_pane_widget2 != NULL)
3350         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3351
3352     gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3353
3354     /* welcome pane */
3355     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3356
3357     /* statusbar hbox */
3358     gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
3359
3360     /* filter toolbar in statusbar hbox */
3361     if (prefs.filter_toolbar_show_in_statusbar) {
3362         gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
3363     }
3364
3365 #ifdef HAVE_AIRPCAP
3366     /* airpcap toolbar */
3367     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3368 #endif
3369
3370     /* statusbar */
3371     gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
3372     gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
3373     gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
3374
3375     /* hide widgets on users recent settings */
3376     main_widgets_show_or_hide();
3377
3378     gtk_widget_show(main_vbox);
3379 }
3380
3381 static void
3382 is_widget_visible(GtkWidget *widget, gpointer data)
3383 {
3384     gboolean *is_visible = data;
3385
3386     if (!*is_visible) {
3387         if (GTK_WIDGET_VISIBLE(widget))
3388             *is_visible = TRUE;
3389     }
3390 }
3391
3392
3393 #ifdef SHOW_WELCOME_PAGE
3394 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
3395    As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
3396 GtkWidget *
3397 welcome_item(gchar *stock_item, gchar * label, gchar * message, GtkSignalFunc callback, void *callback_data)
3398 {
3399     GtkWidget *w, *item_hb;
3400 #if GTK_MAJOR_VERSION >= 2
3401     gchar *formatted_message;
3402 #endif
3403
3404
3405     item_hb = gtk_hbox_new(FALSE, 1);
3406
3407     w = BUTTON_NEW_FROM_STOCK(stock_item);
3408     WIDGET_SET_SIZE(w, 60, 60);
3409 #if GTK_MAJOR_VERSION >= 2
3410     gtk_button_set_label(GTK_BUTTON(w), label);
3411 #endif
3412     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
3413     SIGNAL_CONNECT(w, "clicked", callback, callback_data);
3414
3415     w = gtk_label_new(message);
3416         gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3417 #if GTK_MAJOR_VERSION >= 2
3418     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
3419     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3420     g_free(formatted_message);
3421 #endif
3422
3423     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
3424
3425     return item_hb;
3426 }
3427
3428
3429 /* XXX - the layout has to be improved */
3430 GtkWidget *
3431 welcome_new(void)
3432 {
3433     GtkWidget *welcome_scrollw, *welcome_hb, *welcome_vb, *item_hb;
3434     GtkWidget *w, *icon;
3435     gchar * message;
3436
3437
3438     welcome_scrollw = scrolled_window_new(NULL, NULL);
3439
3440     welcome_hb = gtk_hbox_new(FALSE, 1);
3441         /*gtk_container_border_width(GTK_CONTAINER(welcome_hb), 20);*/
3442
3443     welcome_vb = gtk_vbox_new(FALSE, 1);
3444
3445     item_hb = gtk_hbox_new(FALSE, 1);
3446
3447     icon = xpm_to_widget_from_parent(top_level, wsicon64_xpm);
3448     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 5);
3449
3450 #if GTK_MAJOR_VERSION < 2
3451     message = "Welcome to Wireshark!";
3452 #else
3453     message = "<span weight=\"bold\" size=\"25000\">" "Welcome to Wireshark!" "</span>";
3454 #endif
3455     w = gtk_label_new(message);
3456 #if GTK_MAJOR_VERSION >= 2
3457     gtk_label_set_markup(GTK_LABEL(w), message);
3458 #endif
3459     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3460     gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
3461
3462     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3463
3464     w = gtk_label_new("What would you like to do?");
3465     gtk_box_pack_start(GTK_BOX(welcome_vb), w, FALSE, FALSE, 10);
3466     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3467
3468 #ifdef HAVE_LIBPCAP
3469     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
3470         "Capture",
3471         "Capture live data from your network",
3472         GTK_SIGNAL_FUNC(capture_prep_cb), NULL);
3473     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3474 #endif
3475
3476     item_hb = welcome_item(GTK_STOCK_OPEN,
3477         "Open",
3478         "Open a previously captured file",
3479         GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
3480     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3481
3482 #if (GLIB_MAJOR_VERSION >= 2)
3483     item_hb = welcome_item(GTK_STOCK_HOME,
3484         "Home",
3485         "Visit the Wireshark homepage",
3486         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
3487     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3488
3489     item_hb = welcome_item(WIRESHARK_STOCK_WEB_SUPPORT,
3490         "User's Guide",
3491         "Open the Wireshark User's Guide",
3492         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3493     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3494 #endif
3495
3496     /* the end */
3497     w = gtk_label_new("");
3498     gtk_box_pack_start(GTK_BOX(welcome_vb), w, TRUE, TRUE, 0);
3499
3500     w = gtk_label_new("");
3501     gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
3502
3503     gtk_box_pack_start(GTK_BOX(welcome_hb), welcome_vb, TRUE, TRUE, 0);
3504
3505     w = gtk_label_new("");
3506     gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
3507
3508     gtk_widget_show_all(welcome_hb);
3509
3510     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
3511                                           welcome_hb);
3512     gtk_widget_show_all(welcome_scrollw);
3513
3514     return welcome_scrollw;
3515 }
3516 #else
3517 static GtkWidget *
3518 welcome_new(void)
3519 {
3520     /* this is just a dummy to fill up window space, simply showing nothing */
3521     return scrolled_window_new(NULL, NULL);
3522 }
3523 #endif
3524
3525
3526
3527 /*
3528  * XXX - this doesn't appear to work with the paned widgets in
3529  * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
3530  * and the other pane doesn't grow to take up the rest of the pane.
3531  * It does appear to work with GTK+ 2.x.
3532  */
3533 void
3534 main_widgets_show_or_hide(void)
3535 {
3536     gboolean main_second_pane_show;
3537
3538     if (recent.main_toolbar_show) {
3539         gtk_widget_show(main_tb);
3540     } else {
3541         gtk_widget_hide(main_tb);
3542     }
3543
3544     /*
3545      * Show the status hbox if either:
3546      *
3547      *    1) we're showing the filter toolbar and we want it in the status
3548      *       line
3549      *
3550      * or
3551      *
3552      *    2) we're showing the status bar.
3553      */
3554     if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
3555          recent.statusbar_show) {
3556         gtk_widget_show(stat_hbox);
3557     } else {
3558         gtk_widget_hide(stat_hbox);
3559     }
3560
3561     if (recent.statusbar_show) {
3562         gtk_widget_show(status_pane);
3563     } else {
3564         gtk_widget_hide(status_pane);
3565     }
3566
3567     if (recent.filter_toolbar_show) {
3568         gtk_widget_show(filter_tb);
3569     } else {
3570         gtk_widget_hide(filter_tb);
3571     }
3572
3573 #ifdef HAVE_AIRPCAP
3574     if (recent.airpcap_toolbar_show) {
3575         gtk_widget_show(airpcap_tb);
3576     } else {
3577         gtk_widget_hide(airpcap_tb);
3578     }
3579 #endif
3580
3581     if (recent.packet_list_show && have_capture_file) {
3582         gtk_widget_show(pkt_scrollw);
3583     } else {
3584         gtk_widget_hide(pkt_scrollw);
3585     }
3586
3587     if (recent.tree_view_show && have_capture_file) {
3588         gtk_widget_show(tv_scrollw);
3589     } else {
3590         gtk_widget_hide(tv_scrollw);
3591     }
3592
3593     if (recent.byte_view_show && have_capture_file) {
3594         gtk_widget_show(byte_nb_ptr);
3595     } else {
3596         gtk_widget_hide(byte_nb_ptr);
3597     }
3598
3599     if (have_capture_file) {
3600         gtk_widget_show(main_first_pane);
3601     } else {
3602         gtk_widget_hide(main_first_pane);
3603     }
3604
3605     /*
3606      * Is anything in "main_second_pane" visible?
3607      * If so, show it, otherwise hide it.
3608      */
3609     main_second_pane_show = FALSE;
3610     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3611                           &main_second_pane_show);
3612     if (main_second_pane_show) {