Ringbuffer rework.
[obnox/wireshark/wip.git] / gtk / main.c
index 52e602e3441ed99fd1ed4bb5b4e0dc8edb321cfe..a792b84e64b95d37544e6856916568d1e212a36c 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.281 2003/02/17 07:50:49 oabad Exp $
+ * $Id: main.c,v 1.298 2003/06/22 16:07:23 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include <pcap.h>
 #endif
 
-#ifdef HAVE_LIBZ
-#include <zlib.h>      /* to get the libz version number */
-#endif
-
 #ifdef NEED_SNPRINTF_H
 # include "snprintf.h"
 #endif
 
-#ifdef HAVE_SOME_SNMP
-
-#ifdef HAVE_NET_SNMP
-#include <net-snmp/version.h>
-#endif /* HAVE_NET_SNMP */
-
-#ifdef HAVE_UCD_SNMP
-#include <ucd-snmp/version.h>
-#endif /* HAVE_UCD_SNMP */
-
-#endif /* HAVE_SOME_SNMP */
-
 #ifdef NEED_STRERROR_H
 #include "strerror.h"
 #endif
 #include "register.h"
 #include "ringbuffer.h"
 #include "ui_util.h"
-#include "../ui_util.h"
 #include "image/clist_ascend.xpm"
 #include "image/clist_descend.xpm"
 #include "../tap.h"
+#include "../util.h"
 #include "compat_macros.h"
 
 #ifdef WIN32
@@ -154,7 +138,7 @@ guint            m_font_height, m_font_width;
 PangoFontDescription *m_r_font, *m_b_font;
 #endif
 static guint    main_ctx, file_ctx, help_ctx;
-static GString *comp_info_str;
+static GString *comp_info_str, *runtime_info_str;
 gchar       *ethereal_path = NULL;
 gchar       *last_open_dir = NULL;
 gint   root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
@@ -187,14 +171,14 @@ void
 about_ethereal( GtkWidget *w _U_, gpointer data _U_ ) {
   simple_dialog(ESD_TYPE_INFO, NULL,
                "Ethereal - Network Protocol Analyzer\n"
-               "Version " VERSION " (C) 1998-2002 Gerald Combs <gerald@ethereal.com>\n"
-                "Compiled %s\n\n"
+               "Version " VERSION " (C) 1998-2003 Gerald Combs <gerald@ethereal.com>\n"
+                "%s\n%s\n\n"
 
                "Check the man page for complete documentation and\n"
                "for the list of contributors.\n"
 
                "\nSee http://www.ethereal.com/ for more information.",
-                 comp_info_str->str);
+                 comp_info_str->str, runtime_info_str->str);
 }
 
 #if GTK_MAJOR_VERSION < 2
@@ -230,9 +214,9 @@ goto_framenum_cb(GtkWidget *w _U_, gpointer data _U_)
        hfinfo = finfo_selected->hfinfo;
        g_assert(hfinfo);
        if (hfinfo->type == FT_FRAMENUM) {
-               framenum = fvalue_get_integer(finfo_selected->value);
-               if (framenum != 0)
-                       packet_list_set_selected_row(framenum - 1);
+           framenum = fvalue_get_integer(finfo_selected->value);
+           if (framenum != 0)
+               goto_frame(&cfile, framenum);
        }
     }
 }
@@ -319,7 +303,7 @@ match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -328,7 +312,7 @@ match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -337,7 +321,7 @@ match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -346,7 +330,7 @@ match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -355,7 +339,7 @@ match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -364,7 +348,7 @@ match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -373,7 +357,7 @@ prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_REPLACE,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -382,7 +366,7 @@ prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -391,7 +375,7 @@ prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -400,7 +384,7 @@ prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -409,7 +393,7 @@ prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
@@ -418,7 +402,7 @@ prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 static gchar *
@@ -1190,26 +1174,25 @@ static void
 print_usage(gboolean print_ver) {
 
   if (print_ver) {
-    fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
-         comp_info_str->str);
+    fprintf(stderr, "This is GNU " PACKAGE " " VERSION "\n%s\n%s\n",
+         comp_info_str->str, runtime_info_str->str);
   }
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
+  fprintf(stderr, "\n%s [ -vh ] [ -klnpQS ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
-  fprintf(stderr, "\t[ -c <count> ] [ -f <capture filter> ] [ -i <interface> ]\n");
-  fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
+  fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
+  fprintf(stderr, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
+  fprintf(stderr, "\t[ -i <interface> ] [ -m <medium font> ] [ -N <resolving> ]\n");
   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
   fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
   fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
   fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n");
 #else
-  fprintf(stderr, "\n%s [ -vh ] [ -B <byte view height> ] [ -m <medium font> ]\n",
+  fprintf(stderr, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -n ] [ -N <resolving> ]\n");
-  fprintf(stderr, "\t[ -o <preference setting> ... [ -P <packet list height> ]\n");
-  fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -t <time stamp format> ]\n");
-  fprintf(stderr, "\t[ -T <tree view height> ] [ <infile> ]\n");
+  fprintf(stderr, "\t[ -N <resolving> ] [ -o <preference setting> ...\n");
+  fprintf(stderr, "\t[ -P <packet list height> ] [ -r <infile> ] [ -R <read filter> ]\n");
+  fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ] [ <infile> ]\n");
 #endif
 }
 
@@ -1220,11 +1203,12 @@ show_version(void)
   create_console();
 #endif
 
-  printf("%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
+  printf("%s %s\n%s\n%s\n", PACKAGE, VERSION, comp_info_str->str,
+         runtime_info_str->str);
 }
 
 static int
-get_positive_int(const char *string, const char *name)
+get_natural_int(const char *string, const char *name)
 {
   long number;
   char *p;
@@ -1240,11 +1224,6 @@ get_positive_int(const char *string, const char *name)
            name, string);
     exit(1);
   }
-  if (number == 0) {
-    fprintf(stderr, "ethereal: The specified %s \"%s\" is zero\n",
-            name, string);
-    exit(1);
-  }
   if (number > INT_MAX) {
     fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
            name, string, INT_MAX);
@@ -1253,6 +1232,22 @@ get_positive_int(const char *string, const char *name)
   return number;
 }
 
+static int
+get_positive_int(const char *string, const char *name)
+{
+  long number;
+
+  number = get_natural_int(string, name);
+
+  if (number == 0) {
+    fprintf(stderr, "ethereal: The specified %s is zero\n",
+           name);
+    exit(1);
+  }
+
+  return number;
+}
+
 #ifdef HAVE_LIBPCAP
 /*
  * Given a string of the form "<autostop criterion>:<value>", as might appear
@@ -1300,9 +1295,58 @@ set_autostop_criterion(const char *autostoparg)
   *colonp = ':'; /* put the colon back */
   return TRUE;
 }
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question.  Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(const char *arg)
+{
+  guchar *p = NULL, *colonp;
+
+  colonp = strchr(arg, ':');
+
+  if (colonp != NULL) {
+    p = colonp;
+    *p++ = '\0';
+  }
+
+  capture_opts.ringbuffer_num_files = 
+    get_natural_int(arg, "number of ring buffer files");
+
+  if (colonp == NULL)
+    return TRUE;
+
+  /*
+   * Skip over any white space (there probably won't be any, but
+   * as we allow it in the preferences file, we might as well
+   * allow it here).
+   */
+  while (isspace(*p))
+    p++;
+  if (*p == '\0') {
+    /*
+     * Put the colon back, so if our caller uses, in an
+     * error message, the string they passed us, the message
+     * looks correct.
+     */
+    *colonp = ':';
+    return FALSE;
+  }
+
+  capture_opts.has_ring_duration = TRUE;
+  capture_opts.ringbuffer_duration = get_positive_int(p,
+                                                     "ring buffer duration");
+
+  *colonp = ':';       /* put the colon back */
+  return TRUE;
+}
 #endif
 
-#if defined WIN32 || GTK_MAJOR_VERSION < 2
+#if defined WIN32 || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
 /* 
    Once every 3 seconds we get a callback here which we use to update
    the tap extensions. Since Gtk1 is single threaded we dont have to
@@ -1349,14 +1393,14 @@ update_thread(gpointer data _U_)
 void
 protect_thread_critical_region(void)
 {
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
     g_static_mutex_lock(&update_thread_mutex);
 #endif
 }
 void
 unprotect_thread_critical_region(void)
 {
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
     g_static_mutex_unlock(&update_thread_mutex);
 #endif
 }
@@ -1371,7 +1415,7 @@ typedef struct _ethereal_tap_list {
 static ethereal_tap_list *tap_list=NULL;
 
 void
-register_ethereal_tap(char *cmd, void (*func)(char *arg), char *dummy _U_, void (*dummy2)(void) _U_)
+register_ethereal_tap(char *cmd, void (*func)(char *arg))
 {
        ethereal_tap_list *newtl;
 
@@ -1395,11 +1439,6 @@ main(int argc, char *argv[])
   int                  opt;
   extern char         *optarg;
   gboolean             arg_error = FALSE;
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_VERSION
-  extern char          pcap_version[];
-#endif /* HAVE_PCAP_VERSION */
-#endif /* HAVE_LIBPCAP */
 
 #ifdef WIN32
   WSADATA             wsaData;
@@ -1482,6 +1521,9 @@ main(int argc, char *argv[])
      dissectors, and we must do it before we read the preferences, in
      case any dissectors register preferences. */
   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
+
+  /* Register all tap listeners; we do this before we parse the arguments,
+     as the "-z" argument can specify a registered tap. */
   register_all_tap_listeners();
 
   /* Now register the preferences for any non-dissector modules.
@@ -1521,7 +1563,7 @@ main(int argc, char *argv[])
       else if (strcmp(argv[2], "protocols") == 0)
         proto_registrar_dump_protocols();
       else {
-        fprintf(stderr, "tethereal: Invalid \"%s\" option for -G flag\n",
+        fprintf(stderr, "ethereal: Invalid \"%s\" option for -G flag\n",
                 argv[2]);
         exit(1);
       }
@@ -1530,7 +1572,7 @@ main(int argc, char *argv[])
   }
 
   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined G_THREADS_ENABLED
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined G_THREADS_ENABLED && defined USE_THREADS
   {
       GThread *ut;
       g_thread_init(NULL);
@@ -1538,11 +1580,16 @@ main(int argc, char *argv[])
       ut=g_thread_create(update_thread, NULL, FALSE, NULL);
       g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
   }
-#else  /* WIN32 || GTK1.2 || !G_THREADS_ENABLED */
+#else  /* WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
   /* this is to keep tap extensions updating once every 3 seconds */
   gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
 #endif /* !WIN32 && GTK2 && G_THREADS_ENABLED */
 
+#if HAVE_GNU_ADNS
+  gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
+#endif
+
+
   /* Set the current locale according to the program environment.
    * We haven't localized anything, but some GTK widgets are localized
    * (the file selection dialogue, for example).
@@ -1566,6 +1613,8 @@ main(int argc, char *argv[])
   capture_opts.autostop_filesize = 1;
   capture_opts.ringbuffer_on = FALSE;
   capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+  capture_opts.has_ring_duration = FALSE;
+  capture_opts.ringbuffer_duration = 1;
 
   /* If this is a capture child process, it should pay no attention
      to the "prefs.capture_prom_mode" setting in the preferences file;
@@ -1598,9 +1647,8 @@ main(int argc, char *argv[])
 
   init_cap_file(&cfile);
 
-  /* Assemble the compile-time options */
-  comp_info_str = g_string_new("");
-
+  /* Assemble the compile-time version information string */
+  comp_info_str = g_string_new("Compiled ");
   g_string_append(comp_info_str, "with ");
   g_string_sprintfa(comp_info_str,
 #ifdef GTK_MAJOR_VERSION
@@ -1610,54 +1658,12 @@ main(int argc, char *argv[])
                     "GTK+ (version unknown)");
 #endif
 
-  g_string_append(comp_info_str, ", with ");
-  g_string_sprintfa(comp_info_str,
-#ifdef GLIB_MAJOR_VERSION
-                    "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
-                    GLIB_MICRO_VERSION);
-#else
-                    "GLib (version unknown)");
-#endif
+  g_string_append(comp_info_str, ", ");
+  get_compiled_version_info(comp_info_str);
 
-#ifdef HAVE_LIBPCAP
-  g_string_append(comp_info_str, ", with libpcap ");
-#ifdef HAVE_PCAP_VERSION
-  g_string_append(comp_info_str, pcap_version);
-#else /* HAVE_PCAP_VERSION */
-  g_string_append(comp_info_str, "(version unknown)");
-#endif /* HAVE_PCAP_VERSION */
-#else /* HAVE_LIBPCAP */
-  g_string_append(comp_info_str, ", without libpcap");
-#endif /* HAVE_LIBPCAP */
-
-#ifdef HAVE_LIBZ
-  g_string_append(comp_info_str, ", with libz ");
-#ifdef ZLIB_VERSION
-  g_string_append(comp_info_str, ZLIB_VERSION);
-#else /* ZLIB_VERSION */
-  g_string_append(comp_info_str, "(version unknown)");
-#endif /* ZLIB_VERSION */
-#else /* HAVE_LIBZ */
-  g_string_append(comp_info_str, ", without libz");
-#endif /* HAVE_LIBZ */
-
-/* Oh, this is pretty. */
-/* Oh, ha.  you think that was pretty.  Try this:! --Wes */
-#ifdef HAVE_SOME_SNMP
-
-#ifdef HAVE_UCD_SNMP
-  g_string_append(comp_info_str, ", with UCD-SNMP ");
-  g_string_append(comp_info_str, VersionInfo);
-#endif /* HAVE_UCD_SNMP */
-
-#ifdef HAVE_NET_SNMP
-  g_string_append(comp_info_str, ", with Net-SNMP ");
-  g_string_append(comp_info_str, netsnmp_get_version());
-#endif /* HAVE_NET_SNMP */
-
-#else /* no SNMP library */
-  g_string_append(comp_info_str, ", without UCD-SNMP or Net-SNMP");
-#endif /* HAVE_SOME_SNMP */
+  /* Assemble the run-time version information string */
+  runtime_info_str = g_string_new("Running ");
+  get_runtime_version_info(runtime_info_str);
 
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
@@ -1676,8 +1682,10 @@ main(int argc, char *argv[])
       case 'b':        /* Ringbuffer option */
 #ifdef HAVE_LIBPCAP
         capture_opts.ringbuffer_on = TRUE;
-        capture_opts.ringbuffer_num_files =
-          get_positive_int(optarg, "number of ring buffer files");
+       if (get_ring_arguments(optarg) == FALSE) {
+          fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+          exit(1);
+       }
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
@@ -2014,7 +2022,7 @@ main(int argc, char *argv[])
 #endif
 
   /* Build the column format array */
-  col_init(&cfile.cinfo, prefs->num_cols);
+  col_setup(&cfile.cinfo, prefs->num_cols);
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     cfile.cinfo.col_fmt[i] = get_column_format(i);
     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
@@ -2026,6 +2034,7 @@ main(int argc, char *argv[])
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
     else
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+    cfile.cinfo.col_fence[i] = 0;
     cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
     cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
   }
@@ -2134,10 +2143,12 @@ main(int argc, char *argv[])
      to a file that our parent will read? */
   if (!capture_child) {
 #endif
-    /* No.  Pop up the main window, and read in a capture file if
+    /* No.  Pop up the main window, register menus for taps (which we
+       must do after creating the main window, so that we can add
+       menu items to the main menu), and read in a capture file if
        we were told to. */
-
     create_main_window(pl_size, tv_size, bv_size, prefs);
+    register_all_tap_menus();
     set_menus_for_capture_file(FALSE);
 
     /* open tap windows after creating the main window to avoid GTK warnings */