Implement a ring buffer switch duration:
authordeniel <deniel@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 15 May 2003 13:40:20 +0000 (13:40 +0000)
committerdeniel <deniel@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 15 May 2003 13:40:20 +0000 (13:40 +0000)
when the new "Rotate capture file every n second(s)" checkbox or the
-b <# of file>[:<duration>] argument are used, [t]ethereal will skip to the
next ring buffer file if the specified duration has elapsed (even if the
specified capture size is not reached). This is useful when you want to have
separate capture files per hour or day for instance.

I let the autostop filesize parameter mandatory (i.e. the "rotate capture
file after n kilobytes") but this could be no longer strictly necessary when
that new feature is used ...

Another point: it might be interesting to really truncate the file at the
switch and not the closure ... According to user comments and my own real
case tests, I might plan to enhance this point and others (still ring buffer
related) in the future.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@7678 f5534014-38df-0310-8fa8-9805f1628bb7

capture.c
capture.h
doc/ethereal.pod.template
doc/tethereal.pod.template
gtk/capture_dlg.c
gtk/main.c
tethereal.c

index fffc3c2949b773cec5c5c6fe159c84bbe9ba77e1..74ee00f8e09e074abd4e798877a0f31b473776e3 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.206 2003/04/24 09:07:36 guy Exp $
+ * $Id: capture.c,v 1.207 2003/05/15 13:33:53 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -1368,6 +1368,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   int         err, inpkts;
   condition  *cnd_stop_capturesize = NULL;
   condition  *cnd_stop_timeout = NULL;
+  condition  *cnd_ring_timeout = NULL;
   unsigned int i;
   static const char capstart_msg = SP_CAPSTART;
   char        errmsg[4096+1];
@@ -1757,6 +1758,10 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     cnd_stop_timeout =
         cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts.autostop_duration);
 
+  if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+    cnd_ring_timeout =
+       cnd_new(CND_CLASS_TIMEOUT, capture_opts.ringbuffer_duration);
+
   while (ld.go) {
     while (gtk_events_pending()) gtk_main_iteration();
 
@@ -1861,6 +1866,9 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
           if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
             /* File switch succeeded: reset the condition */
             cnd_reset(cnd_stop_capturesize);
+           if (cnd_ring_timeout) {
+             cnd_reset(cnd_ring_timeout);
+           }
           } else {
             /* File switch failed: stop here */
             ld.go = FALSE;
@@ -1918,8 +1926,18 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
       if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
         /* The specified capture time has elapsed; stop the capture. */
         ld.go = FALSE;
+      } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+       /* time elasped for this ring file, swith to the next */
+       if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
+         /* File switch succeeded: reset the condition */
+         cnd_reset(cnd_ring_timeout);
+       } else {
+         /* File switch failed: stop here */
+         ld.go = FALSE;
+       }
       }
     }
+
   } /* while (ld.go) */
 
   /* delete stop conditions */
@@ -1927,6 +1945,8 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     cnd_delete(cnd_stop_capturesize);
   if (cnd_stop_timeout != NULL)
     cnd_delete(cnd_stop_timeout);
+  if (cnd_ring_timeout != NULL)
+    cnd_delete(cnd_ring_timeout);
 
   if (ld.pcap_err) {
     snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
index 961068595ff51fce6331f9be297a4891a41c97a2..33287a30a8ed6b5df81451f340bba811195081eb 100644 (file)
--- a/capture.h
+++ b/capture.h
@@ -1,7 +1,7 @@
 /* capture.h
  * Definitions for packet capture windows
  *
- * $Id: capture.h,v 1.34 2003/01/09 19:37:14 guy Exp $
+ * $Id: capture.h,v 1.35 2003/05/15 13:33:53 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -49,6 +49,8 @@ typedef struct {
        gint32 autostop_filesize;       /* Maximum capture file size */
        gboolean ringbuffer_on;         /* TRUE if ring buffer in use */
        guint32 ringbuffer_num_files;   /* Number of ring buffer files */
+       gboolean has_ring_duration;     /* TRUE if ring duration specified */
+       gint32 ringbuffer_duration;     /* Switch file after n seconds */
 } capture_options;
 
 extern capture_options capture_opts;
index 8b7381abc2bcb7a5b0b62ff14e8813e873ba6013..e916f25dcc1df0d6dde5e77b0d956df1980e6338 100644 (file)
@@ -7,7 +7,7 @@ ethereal - Interactively browse network traffic
 
 B<ethereal>
 S<[ B<-a> capture autostop condition ] ...>
-S<[ B<-b> number of ring buffer files ]>
+S<[ B<-b> number of ring buffer files [:duration] ]>
 S<[ B<-B> byte view height ]>
 S<[ B<-c> count ]>
 S<[ B<-f> capture filter expression ]>
@@ -128,6 +128,10 @@ discard the data in the first file and start writing to that file.  When
 that file fills up, B<Ethereal> will discard the data in the next file
 and start writing to it, and so on.
 
+If the optional duration is specified, B<Ethereal> will switch also 
+to the next file when the specified number of seconds has elapsed even
+if the current file is not completely fills up.
+
 When the capture completes, the files will be renamed to have names
 based on the number of the file and on the date and time at which
 packets most recently started being written to the file.
@@ -1084,7 +1088,12 @@ can save those packets to a file with the I<File:Save As> menu item.
 
 The I<Use ring buffer> check box lets you specify that the capture
 should be done in "ring buffer" mode; the I<Number of files> field
-lets you specify the number of files in the ring buffer.
+lets you specify the number of files in the ring buffer. 
+
+The I<Rotate capture file every ...  second(s)> check box and field lets
+you to specify that the swith to a next ring buffer file should be done
+if the specified duration has elapsed even if the specified capture size
+is not reached.
 
 The I<Update list of packets in real time> check box lets you specify
 whether the display should be updated as packets are captured and, if
@@ -1108,7 +1117,7 @@ running, or the available disk space, may still limit the maximum size
 of a capture file).
 
 If "ring buffer" mode is specified, that field becomes the I<Rotate
-capture file very ...  kilobyte(s)> field, and specifies the number
+capture file every ...  kilobyte(s)> field, and specifies the number
 of kilobytes at which to start writing to a new ring buffer file; the
 check box is forced to be checked, as "ring buffer" mode requires a file
 size to be specified.
index 71736beeb1989127bddc1e382488613424695da7..ce7fde353f7ac5892169ab9ac4db254be012ce4a 100644 (file)
@@ -7,7 +7,7 @@ tethereal - Dump and analyze network traffic
 
 B<tethereal>
 S<[ B<-a> capture autostop condition ] ...>
-S<[ B<-b> number of ring buffer files ]>
+S<[ B<-b> number of ring buffer files [:duration] ]>
 S<[ B<-c> count ]>
 S<[ B<-D> ]>
 S<[ B<-f> capture filter expression ]>
@@ -155,6 +155,10 @@ point it'll discard the data in the first file and start writing to that
 file.  When that file fills up, B<Tethereal> will discard the data in
 the next file and start writing to it, and so on.
 
+If the optional duration is specified, B<Tethereal> will switch also 
+to the next file when the specified number of seconds has elapsed even
+if the current file is not completely fills up.
+
 When the capture completes, the files will be renamed to have names
 based on the number of the file and on the date and time at which
 packets most recently started being written to the file.
index 893c1b3b358c9be6d86033b29510f241d2a88361..2bf3b9514715dc8b21236b6538f9fb910c947376 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_dlg.c
  * Routines for packet capture windows
  *
- * $Id: capture_dlg.c,v 1.77 2003/01/15 05:20:18 guy Exp $
+ * $Id: capture_dlg.c,v 1.78 2003/05/15 13:38:05 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -62,6 +62,8 @@
 #define E_CAP_RING_ON_TB_KEY  "cap_ringbuffer_on_tb"
 #define E_CAP_RING_NBF_LB_KEY "cap_ringbuffer_nbf_lb"
 #define E_CAP_RING_NBF_SB_KEY "cap_ringbuffer_nbf_sb"
+#define E_CAP_RING_DURATION_CB_KEY "cap_ringbuffer_duration_cb"
+#define E_CAP_RING_DURATION_SB_KEY "cap_ringbuffer_duration_sb"
 #define E_CAP_SYNC_KEY        "cap_sync"
 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
 #define E_CAP_COUNT_CB_KEY    "cap_count_cb"
@@ -134,6 +136,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
                 *count_hb, *count_cb, *count_sb, *count_lb,
                 *filesize_hb, *filesize_cb, *filesize_sb, *filesize_lb,
                 *duration_hb, *duration_cb, *duration_sb, *duration_lb,
+               *ring_duration_hb, *ring_duration_cb, *ring_duration_sb, 
+               *ring_duration_lb,
                 *resolv_fr, *resolv_vb,
                 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
                 *bbox, *ok_bt, *cancel_bt;
@@ -141,7 +145,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   GtkAccelGroup *accel_group;
 #endif
   GtkAdjustment *snap_adj, *ringbuffer_nbf_adj,
-                *count_adj, *filesize_adj, *duration_adj;
+               *count_adj, *filesize_adj, *duration_adj, *ring_duration_adj;
   GList         *if_list;
   int           err;
   char          err_str[PCAP_ERRBUF_SIZE];
@@ -354,6 +358,35 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0);
   gtk_widget_show(ringbuffer_nbf_sb);
 
+  /* Ring buffer duration row */
+  ring_duration_hb = gtk_hbox_new(FALSE, 3);
+  gtk_container_add(GTK_CONTAINER(file_vb), ring_duration_hb);
+  gtk_widget_show(ring_duration_hb);
+
+  ring_duration_cb = gtk_check_button_new_with_label("Rotate capture file every");
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ring_duration_cb),
+                             capture_opts.has_ring_duration);
+  SIGNAL_CONNECT(ring_duration_cb, "toggled", 
+                capture_prep_adjust_sensitivity, cap_open_w);
+  gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_cb, 
+                    FALSE, FALSE, 0);
+  gtk_widget_show(ring_duration_cb);
+
+  ring_duration_adj = (GtkAdjustment *)gtk_adjustment_new(capture_opts.ringbuffer_duration,
+    1, INT_MAX, 1.0, 10.0, 0.0);
+  ring_duration_sb = gtk_spin_button_new (ring_duration_adj, 0, 0);
+  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ring_duration_sb), TRUE);
+  WIDGET_SET_SIZE(ring_duration_sb, 80, -1);
+  gtk_box_pack_start (GTK_BOX(ring_duration_hb), ring_duration_sb, 
+                     FALSE, FALSE, 0);
+  gtk_widget_show(ring_duration_sb);
+
+  ring_duration_lb = gtk_label_new("second(s)");
+  gtk_misc_set_alignment(GTK_MISC(ring_duration_lb), 0, 0.5);
+  gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_lb, 
+                    FALSE, FALSE, 0);
+  gtk_widget_show(ring_duration_lb);
+
   /* Display-related options frame */
   display_fr = gtk_frame_new("Display options");
   gtk_container_add(GTK_CONTAINER(main_vb), display_fr);
@@ -556,6 +589,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_ON_TB_KEY,  ringbuffer_on_tb);
   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_LB_KEY,  ringbuffer_nbf_lb);
   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_SB_KEY,  ringbuffer_nbf_sb);
+  OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_CB_KEY,  ring_duration_cb);
+  OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_SB_KEY,  ring_duration_sb);
   OBJECT_SET_DATA(cap_open_w, E_CAP_SYNC_KEY,  sync_cb);
   OBJECT_SET_DATA(cap_open_w, E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
   OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_CB_KEY, count_cb);
@@ -721,6 +756,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
             *count_cb, *count_sb,
             *filesize_cb, *filesize_sb,
             *duration_cb, *duration_sb,
+            *ring_duration_cb, *ring_duration_sb,
             *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
   gchar *if_text;
   gchar *if_name;
@@ -737,6 +773,8 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
   file_te   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILE_TE_KEY);
   ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
   ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
+  ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
+  ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
   sync_cb   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
   auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
   count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
@@ -867,6 +905,12 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
   else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
     capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
 
+  capture_opts.has_ring_duration =
+    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb));
+  if (capture_opts.has_ring_duration)
+    capture_opts.ringbuffer_duration =
+      gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ring_duration_sb));
+
   gtk_widget_destroy(GTK_WIDGET(parent_w));
 
   do_capture(save_file);
@@ -911,13 +955,16 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
             *sync_cb, *auto_scroll_cb,
             *count_cb, *count_sb,
             *filesize_cb, *filesize_sb, *filesize_lb,
-            *duration_cb, *duration_sb;
+           *duration_cb, *duration_sb,
+           *ring_duration_cb, *ring_duration_sb;
 
   snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
   snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
   ringbuffer_on_tb  = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
   ringbuffer_nbf_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_LB_KEY);
   ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
+  ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
+  ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
   sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
   auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
   count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
@@ -963,6 +1010,7 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
        of ring buffer files, and its label, sensitive. */
     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), TRUE);
     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
+    gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), TRUE);
 
     /* Also, indicate that the file size is a size at which to switch
        ring buffer files, not a size at which to stop the capture,
@@ -976,6 +1024,7 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
        of ring buffer files, and its label insensitive. */
     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), FALSE);
     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
+    gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), FALSE);
 
     /* Also, indicate that the file size is a size at which to stop the
        capture, not a size at which to switch ring buffer files. */
@@ -998,6 +1047,12 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
      after N seconds" checkbox is on. */
   gtk_widget_set_sensitive(GTK_WIDGET(duration_sb),
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb)));
+
+  /* The ring duration spinbox is sensitive if the "Rotate capture file
+     after N seconds" checkbox is on. */
+  gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_sb),
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb)));
+
 }
 
 #endif /* HAVE_LIBPCAP */
index 28dfaa9fc0af71d8da6eb1db3d05c36a6217b698..a2cbd7ec9ceeaada4b57540b9f486fc972e14adb 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.293 2003/05/04 18:50:56 gerald Exp $
+ * $Id: main.c,v 1.294 2003/05/15 13:38:05 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -1180,7 +1180,8 @@ print_usage(gboolean print_ver) {
 #ifdef HAVE_LIBPCAP
   fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
+  fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
+  fprintf(stderr, "\t[ -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[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
@@ -1285,6 +1286,55 @@ 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, *colonp;
+
+  colonp = strchr(arg, ':');
+
+  if (colonp != NULL) {
+    p = colonp;
+    *p++ = '\0';
+  }
+
+  capture_opts.ringbuffer_num_files = 
+    get_positive_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
@@ -1554,6 +1604,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;
@@ -1621,8 +1673,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;
index f38d02a80f15585e52e4dd48abc0d4d774084b7c..01d90cfd841095ec52663caaee74eb5e615e6a53 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.183 2003/05/14 10:31:15 deniel Exp $
+ * $Id: tethereal.c,v 1.184 2003/05/15 13:33:53 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -183,6 +183,8 @@ typedef struct {
        gint32 autostop_filesize;       /* Maximum capture file size */
        gboolean ringbuffer_on;         /* TRUE if ring buffer in use */
        guint32 ringbuffer_num_files;   /* Number of ring buffer files */
+       gboolean has_ring_duration;     /* TRUE if ring duration specified */
+       gint32 ringbuffer_duration;     /* Switch file after n seconds */
 } capture_options;
 
 static capture_options capture_opts = {
@@ -198,8 +200,10 @@ static capture_options capture_opts = {
                                           specified by default */
        0,                              /* maximum capture file size */
        FALSE,                          /* ring buffer off by default */
-       RINGBUFFER_MIN_NUM_FILES        /* default number of ring buffer
+       RINGBUFFER_MIN_NUM_FILES,       /* default number of ring buffer
                                           files */
+       FALSE,                          /* Switch ring file after some */
+       0                               /* specified time is off by default */
 };
 
 #ifdef SIGINFO
@@ -220,7 +224,7 @@ print_usage(gboolean print_ver)
 #ifdef HAVE_LIBPCAP
   fprintf(stderr, "\nt%s [ -DvVhqSlp ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -b <number of ring buffer files> ] [ -c <count> ]\n");
+  fprintf(stderr, "\t[ -b <number of ring buffer files>[:<duration>] ] [ -c <count> ]\n");
   fprintf(stderr, "\t[ -f <capture filter> ] [ -F <output file type> ]\n");
   fprintf(stderr, "\t[ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
@@ -317,6 +321,55 @@ 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, *colonp;
+
+  colonp = strchr(arg, ':');
+
+  if (colonp != NULL) {
+    p = colonp;
+    *p++ = '\0';
+  }
+
+  capture_opts.ringbuffer_num_files = 
+    get_positive_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
 
 /* structure to keep track of what tap listeners have been registered.
@@ -461,8 +514,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;
@@ -920,6 +975,7 @@ capture(int out_file_type)
   char        errmsg[1024+1];
   condition  *volatile cnd_stop_capturesize = NULL;
   condition  *volatile cnd_stop_timeout = NULL;
+  condition  *volatile cnd_ring_timeout = NULL;
 #ifndef _WIN32
   static const char ppamsg[] = "can't find PPA for ";
   char       *libpcap_warn;
@@ -1113,6 +1169,10 @@ capture(int out_file_type)
     cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
                                (gint32)capture_opts.autostop_duration);
 
+  if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+    cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT, 
+                              capture_opts.ringbuffer_duration);
+
   if (!setjmp(ld.stopenv)) {
     ld.go = TRUE;
     ld.packet_count = 0;
@@ -1191,6 +1251,15 @@ capture(int out_file_type)
     } else if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
       /* The specified capture time has elapsed; stop the capture. */
       ld.go = FALSE;
+    } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+      /* time elasped for this ring file, swith to the next */
+      if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
+       /* File switch succeeded: reset the condition */
+       cnd_reset(cnd_ring_timeout);
+      } else {
+       /* File switch failed: stop here */
+       ld.go = FALSE;
+      }
     } else if (inpkts > 0) {
       if (capture_opts.autostop_count != 0 &&
                  ld.packet_count >= capture_opts.autostop_count) {
@@ -1208,6 +1277,9 @@ capture(int out_file_type)
           if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
             /* File switch succeeded: reset the condition */
             cnd_reset(cnd_stop_capturesize);
+           if (cnd_ring_timeout) {
+             cnd_reset(cnd_ring_timeout);
+           }
           } else {
             /* File switch failed: stop here */
             volatile_err = loop_err;
@@ -1235,6 +1307,8 @@ capture(int out_file_type)
     cnd_delete(cnd_stop_capturesize);
   if (cnd_stop_timeout != NULL)
     cnd_delete(cnd_stop_timeout);
+  if (cnd_ring_timeout != NULL)
+    cnd_delete(cnd_ring_timeout);
 
   if ((cfile.save_file != NULL) && !quiet) {
     /* We're saving to a file, which means we're printing packet counts