Ethereal-dev: [Ethereal-dev] revised patch to enable SIGINT trace stops

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Neil Horman <nhorman@xxxxxxxxxxxxx>
Date: Fri, 12 Sep 2003 08:43:27 -0400
Guy-
Hey there! As promised, I revised my patch to allow both a user to press ctrl-c in a window or send a SIGINT to ethereal to stop an in-progress trace. I assumed since I didn't hear back from you that SIGINT was the most appropriate signal to use here (as opposed to SIGUSR2). Anywho, let me know what you think. Thanks!
Neil

Index: capture.c
===================================================================
RCS file: /cvsroot/ethereal/capture.c,v
retrieving revision 1.208
diff -u -r1.208 capture.c
--- capture.c	23 Jul 2003 05:01:15 -0000	1.208
+++ capture.c	12 Sep 2003 12:39:07 -0000
@@ -1,4 +1,4 @@
-/* capture.c
+/* CAPTURe.c
  * Routines for packet capture windows
  *
  * $Id: capture.c,v 1.208 2003/07/23 05:01:15 guy Exp $
@@ -247,6 +247,37 @@
 int child_process;
 #endif
 
+
+/*
+ * This needs to be static, so that the SIGUSR1 handler can clear the "go"
+ * flag.
+ */
+static loop_data   ld;
+
+/*
+ *This is the ASCII value of a ctrl-c
+ */
+#define CTRL_C 0x03
+static void key_press_win(GtkWidget *widget,
+	 	   GdkEventKey *key,	
+                   gpointer   callback_data )
+{
+   /*
+    *check to see if the key press event
+    *is a ctrl-c.  If it is, end the capture
+    */
+   if((char)*(key->string) == CTRL_C)
+   {
+      ld.go = FALSE; 
+   }
+}
+
+
+int capture_in_progress()
+{
+   return ld.go;
+}
+
 /* Add a string pointer to a NULL-terminated array of string pointers. */
 static char **
 add_arg(char **args, int *argc, char *arg)
@@ -1342,12 +1373,6 @@
 }
 #endif
 
-/*
- * This needs to be static, so that the SIGUSR1 handler can clear the "go"
- * flag.
- */
-static loop_data   ld;
-
 /* Do the low-level work of a capture.
    Returns TRUE if it succeeds, FALSE otherwise. */
 int
@@ -1696,6 +1721,8 @@
   main_vb = gtk_vbox_new(FALSE, 1);
   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
   gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
+  gtk_signal_connect(GTK_OBJECT(cap_w), "key_press_event", 
+			(GtkSignalFunc) key_press_win, NULL );
   gtk_widget_show(main_vb);
 
   counts_fr = gtk_frame_new("Captured Frames");
@@ -2182,7 +2209,7 @@
   }
 }
 
-static void
+void
 stop_capture(int signo _U_)
 {
   ld.go = FALSE;
@@ -2209,6 +2236,8 @@
 #ifndef _WIN32
   if (fork_child != -1)
       kill(fork_child, SIGUSR1);
+  else
+      ld.go = FALSE;
 #endif
 }
 
Index: capture.h
===================================================================
RCS file: /cvsroot/ethereal/capture.h,v
retrieving revision 1.35
diff -u -r1.35 capture.h
--- capture.h	15 May 2003 13:33:53 -0000	1.35
+++ capture.h	12 Sep 2003 12:39:07 -0000
@@ -58,6 +58,11 @@
 extern int quit_after_cap; /* Makes a "capture only mode". Implies -k */
 extern gboolean capture_child;	/* if this is the child for "-S" */
 
+/*
+ *tell us if we are in the middle of a capture
+ */
+int caputure_in_progress();
+
 /* Open a specified file, or create a temporary file, and start a capture
    to the file in question. */
 void   do_capture(const char *save_file);
@@ -67,6 +72,9 @@
 
 /* Stop a capture from a menu item. */
 void   capture_stop(void);
+
+/* Stop a capture from a signal */
+void stop_capture(int signo _U_);
 
 /* Terminate the capture child cleanly when exiting. */
 void   kill_capture_child(void);
Index: gtk/main.c
===================================================================
RCS file: /cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.310
diff -u -r1.310 main.c
--- gtk/main.c	10 Sep 2003 05:35:26 -0000	1.310
+++ gtk/main.c	12 Sep 2003 12:39:08 -0000
@@ -43,6 +43,7 @@
 
 #include <string.h>
 #include <ctype.h>
+#include <signal.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -146,6 +147,12 @@
 gchar       *last_open_dir = NULL;
 gint   root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
 
+
+/*
+ *the cascaded signal handler, if it exists
+ */
+__sighandler_t cascade;
+
 ts_type timestamp_type = RELATIVE;
 
 #if GTK_MAJOR_VERSION < 2
@@ -1483,6 +1490,56 @@
 
 }
 
+/*
+ *This is the ASCII value of a ctrl-c
+ */
+#define CTRL_C 0x03
+static void key_press_handler(GtkWidget *widget,
+                   GdkEventKey *key,
+                   gpointer   callback_data )
+{
+   /*
+    *check to see if the key press event
+    *is a ctrl-c.  If it is, end the capture
+    */
+   if((char)*(key->string) == CTRL_C)
+   {
+      capture_stop(); 
+   }
+}
+
+/*
+ *Signal handler for SIGINT signal
+ */
+void sigint_catcher(int sig)
+{
+   /*
+    *if we are in the middle of a capture
+    *this SIGINT was meant to stop the
+    *capture
+    */
+   if(capture_in_progress() == TRUE)
+   {
+      capture_stop();
+   }
+   else
+   {
+      /*
+       *otherwise it was meant to do
+       *whatever the previous signal handler
+       *does with it, if anything
+       */
+      if((cascade != SIG_ERR) &&
+         (cascade != SIG_DFL) &&
+         (cascade != SIG_IGN) &&
+         (cascade != NULL))
+      {
+         cascade(sig);
+      }
+   } 
+}
+
+
 /* And now our feature presentation... [ fade to music ] */
 int
 main(int argc, char *argv[])
@@ -1659,6 +1716,11 @@
   /* Let GTK get its args */
   gtk_init (&argc, &argv);
 
+  /*
+   *after we init gtk, we should register to override the SIGINT handler
+   */
+  cascade = signal(SIGINT,sigint_catcher);
+
   /* Read the preference files. */
   prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
                      &pf_open_errno, &pf_read_errno, &pf_path);
@@ -2663,6 +2725,8 @@
 
     /* Main window */
     top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_signal_connect(GTK_OBJECT(top_level), "key_press_event",
+                        (GtkSignalFunc) key_press_handler, NULL );
     gtk_widget_set_name(top_level, "main window");
     SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
                    NULL);