Ethereal-dev: [ethereal-dev] John's almost-real-time capture
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Gilbert Ramirez <gram@xxxxxxxxxx>
Date: Thu, 6 May 1999 14:45:08 -0500
Can someone else test this patch to ethereal? It works fine on John's red hat box, but I cannot get it to work on my Debian Linux box or on my Solaris 2.6 box. To invoke, use "ethereal -F" or "ethereal -F -S". When I try to capture after doing this, I get Xlib errors! This is with both gtk+-1.0 and gtk+-1.2. --gilbert
diff -urN ethereal/capture.c ethereal-rtcap/capture.c
--- ethereal/capture.c Mon May 3 16:14:24 1999
+++ ethereal-rtcap/capture.c Mon May 3 13:27:13 1999
@@ -43,6 +43,7 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#include <signal.h>
#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
@@ -70,6 +71,10 @@
extern GtkWidget *info_bar;
extern guint file_ctx;
+extern int fork_mode;
+int fork_child;
+extern int quit_after_cap;
+
/* File selection data keys */
#define E_CAP_PREP_FS_KEY "cap_prep_fs"
#define E_CAP_PREP_TE_KEY "cap_prep_te"
@@ -84,6 +89,10 @@
/* Capture filter key */
#define E_CAP_FILT_TE_KEY "cap_filt_te"
+/* how often to force an fflush */
+#define DUMP_FREQ 4
+FILE *dump_file_handle;
+
GList *
get_interface_list() {
GList *il = NULL;
@@ -337,7 +346,7 @@
cf.cfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
}
cf.count =
- atoi(g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry))));
+ atoi( g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry))));
cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
if (cf.snap < 1)
cf.snap = MAX_PACKET_SIZE;
@@ -354,7 +363,31 @@
cf.save_file = tempnam(NULL, "ether");
cf.user_saved = 0;
- capture();
+ if( fork_mode ){ /* use fork() for capture */
+ char ssnap[24];
+ char scount[24]; /* need a constant for len of numbers */
+
+ sprintf(ssnap,"%d",cf.snap); /* in liu of itoa */
+ sprintf(scount,"%d",cf.count);
+ signal(SIGCHLD, SIG_IGN);
+ if((fork_child = fork()) == 0){
+ /* args: -k -- capture
+ * -i interface specification
+ * -w file to write
+ * -c count to capture
+ * -Q quit after capture (forces -k)
+ * -s snaplen
+ * should add -b -m -t from this invocation: TODO
+ */
+ execlp("ethereal","ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+ "-c",scount,"-s", ssnap,0);
+ }
+ else {
+ cf.filename = cf.save_file;
+ }
+ }
+ else
+ capture();
}
void
@@ -401,6 +434,9 @@
pcap_close(pch);
return;
}
+ /* save the file handle for flushing when a SIGUSR1 arrives */
+ dump_file_handle = (FILE *)ld.pdh;
+
ld.linktype = pcap_datalink(pch);
if (cf.cfilter) {
@@ -504,6 +540,11 @@
"that you have the proper interface specified.");
}
+ if( quit_after_cap ){
+ /* DON'T unlink the save file. Presumably someone wants it. */
+ gtk_exit(0);
+ }
+
if (cf.save_file) load_cap_file(cf.save_file, &cf);
#ifdef USE_ITEM
set_menu_sensitivity("/File/Save", TRUE);
@@ -534,6 +575,7 @@
capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd) {
+ static int dump_count = 0;
loop_data *ld = (loop_data *) user;
if ((++ld->counts.total >= ld->max) && (ld->max > 0))
@@ -543,6 +585,13 @@
/* Currently, pcap_dumper_t is a FILE *. Let's hope that doesn't change. */
if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd);
+ /* flush every DUMP_FREQ times */
+
+ if ( !dump_count ){
+ fflush((FILE *)ld->pdh);
+ }
+ dump_count = (dump_count + 1) % DUMP_FREQ;
+
switch (ld->linktype) {
case DLT_EN10MB :
capture_eth(pd, phdr->caplen, &ld->counts);
diff -urN ethereal/ethereal.c ethereal-rtcap/ethereal.c
--- ethereal/ethereal.c Mon May 3 16:15:04 1999
+++ ethereal-rtcap/ethereal.c Mon May 3 13:33:24 1999
@@ -55,6 +55,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
+#include <signal.h>
#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
@@ -97,6 +98,13 @@
GtkStyle *item_style;
+int sync_mode; /* allow sync */
+
+int fork_mode; /* fork a child to do the capture */
+extern int fork_child;
+int quit_after_cap; /* Makes a "capture only mode". Implies -k */
+extern FILE *dump_file_handle;
+
#define E_DFILTER_TE_KEY "display_filter_te"
/* About Ethereal window */
@@ -281,7 +289,10 @@
(file_sel)->cancel_button), "clicked", (GtkSignalFunc)
gtk_widget_destroy, GTK_OBJECT (file_sel));
- gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
+ if( fork_mode && (cf.save_file != NULL) )
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), cf.save_file);
+ else
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
gtk_widget_show(file_sel);
}
@@ -394,6 +405,28 @@
if (cf.dfilter) g_free(cf.dfilter);
cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
+ /* JJM */
+
+ /* MUST check fork_mode to see 1) if we have a "fork_child" value, and 2) if
+ * the process will catch the signal
+ */
+ if( sync_mode && fork_mode){
+ /* first, see if the child is still there */
+ if( !kill(fork_child, 0)){
+ /* we can talk to our child */
+ kill(fork_child, SIGUSR1);
+ /* wait for the file to be written. Probably should pass my pid to child so it
+ * can signal us back when it is done. Then our handler could emit a gtk signal
+ * to force reloading. As it stands I am hoping that we can make this threaded
+ * (using gtk or pthreads) and hence not need this ugliness.
+ */
+
+ /* might cause trouble: both sleep and the itimer use SIGALRM. We use
+ * SIGALRM for dns timeouts.
+ */
+ sleep(2); /* not long enough under heavy load */
+ }
+ }
load_cap_file(cf.filename, &cf);
}
@@ -491,10 +524,7 @@
#endif
}
if (start_capture) {
- if (cf.save_file)
- capture();
- else
- capture();
+ capture();
start_capture = 0;
}
}
@@ -518,6 +548,16 @@
fprintf(stderr, " [-T tree view height] [-w savefile] \n");
}
+/* if we get SIGUSR1 flush the buffer. Allows sync by someone watching our dump */
+void
+flushit (int sig)
+{
+ if(dump_file_handle)
+ fflush(dump_file_handle);
+ signal(SIGUSR1, flushit);
+}
+
+
/* And now our feature presentation... [ fade to music ] */
int
main(int argc, char *argv[])
@@ -545,8 +585,10 @@
gint *col_fmt;
gchar **col_title;
+
/* Let GTK get its args */
gtk_init (&argc, &argv);
+
prefs = read_prefs();
@@ -584,7 +626,7 @@
#endif
/* Now get our args */
- while ((opt = getopt(argc, argv, "b:B:c:hi:m:nP:r:s:t:T:w:v")) != EOF) {
+ while ((opt = getopt(argc, argv, "b:B:c:Fhi:km:nP:Qr:Ss:t:T:w:v")) != EOF) {
switch (opt) {
case 'b': /* Bold font */
bold_font = g_strdup(optarg);
@@ -595,6 +637,9 @@
case 'c': /* Capture xxx packets */
cf.count = atoi(optarg);
break;
+ case 'F': /* Fork to capture */
+ fork_mode = 1;
+ break;
case 'h': /* Print help and exit */
print_usage();
exit(0);
@@ -614,12 +659,19 @@
case 'P': /* Packet list pane height */
pl_size = atoi(optarg);
break;
+ case 'Q': /* Quit after capture (just capture to file) */
+ quit_after_cap = 1;
+ start_capture = 1; /*** -Q implies -k !! ***/
+ break;
case 'r': /* Read capture file xxx */
cf_name = g_strdup(optarg);
break;
case 's': /* Set the snapshot (capture) length */
cf.snap = atoi(optarg);
break;
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ sync_mode = 1;
+ break;
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
timestamp_type = RELATIVE;
@@ -647,6 +699,9 @@
break;
}
}
+
+ if( start_capture)
+ signal(SIGUSR1, flushit); /* catch the flush signal */
/* Build the column format array */
col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
- Follow-Ups:
- Re: [ethereal-dev] John's almost-real-time capture
- From: Laurent Deniel
- Re: [ethereal-dev] John's almost-real-time capture
- From: Guy Harris
- Re: [ethereal-dev] John's almost-real-time capture
- Prev by Date: [ethereal-dev] Linux Weekly News.
- Next by Date: Re: [ethereal-dev] John's almost-real-time capture
- Previous by thread: [ethereal-dev] Linux Weekly News.
- Next by thread: Re: [ethereal-dev] John's almost-real-time capture
- Index(es):





