Move the toolkit-independent code to create a temporary capture file,
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 23 Sep 1999 06:27:27 +0000 (06:27 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 23 Sep 1999 06:27:27 +0000 (06:27 +0000)
and to fork off and run a separate copy of "ethereal" for "-S" and "-F"
captures or just call "capture()" otherwise, out of "gtk/capture_dlg.c"
and into a routine in "capture.c".

If the attempt to create said temporary capture file fails, pop up a
dialog box and don't do the capture.

Have the child capture process send a message upstream after it either
successfully starts the capture and syncs out the header of the capture
file, or fails to start the capture; the message indicates whether it
succeeded or failed, and, if it failed, includes a failure message.
This:

avoids the use of a signal, and thus means we don't have to
worry about whether to capture the signal, or whether to start
or stop capturing depending on whether this particular capture
is in sync mode or not;

lets us pop up the message box for the error in the parent
process if we're in sync mode, rather than doing it in the
child, which didn't work well.

Add a check button to the Capture/Start dialog box, so that we can
control, for each capture, whether it's to be done in sync mode or not.

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

capture.c
capture.h
globals.h
gtk/capture_dlg.c
gtk/main.c

index 9ad3996107161cb4b56aa8c08254066ca19ce398..79e8282c7f9441a3c863df5d979b5f6d0a280de8 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.67 1999/09/11 06:23:22 guy Exp $
+ * $Id: capture.c,v 1.68 1999/09/23 06:27:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -41,6 +41,7 @@
 #include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
@@ -97,7 +98,141 @@ typedef struct _loop_data {
 } loop_data;
 
 void
-capture(void) {
+do_capture(void)
+{
+  char tmpname[128+1];
+  char c;
+  int i;
+  guint byte_count;
+  char *msg;
+
+  /* Choose a random name for the capture buffer */
+  if (cf.save_file && !cf.user_saved) {
+       unlink(cf.save_file); /* silently ignore error */
+       g_free(cf.save_file);
+  }
+  cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
+  if (cf.save_file_fd == -1) {
+    simple_dialog(ESD_TYPE_WARN, NULL,
+       "The file to which the capture would be saved (\"%s\")"
+       "could not be opened: %s.", tmpname, strerror(errno));
+    return;
+  }
+  cf.save_file = g_strdup(tmpname);
+  cf.user_saved = 0;
+  
+  if( fork_mode ){     /*  use fork() for capture */
+    int  fork_child;
+    char ssnap[24];
+    char scount[24];   /* need a constant for len of numbers */
+    char save_file_fd[24];
+    int err;
+
+    sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
+    sprintf(scount,"%d",cf.count);
+    sprintf(save_file_fd,"%d",cf.save_file_fd);
+    signal(SIGCHLD, SIG_IGN);
+    if (sync_mode) pipe(sync_pipe);
+    if((fork_child = fork()) == 0){
+      /* args: -k -- capture
+       * -i interface specification
+       * -w file to write
+       * -W file descriptor to write
+       * -c count to capture
+       * -Q quit after capture (forces -k)
+       * -s snaplen
+       * -S sync mode
+       * -m / -b fonts
+       * -f "filter expression"
+       */
+       if (sync_mode) {
+        close(1);
+        dup(sync_pipe[1]);
+        close(sync_pipe[0]);
+        execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
+               "-w", cf.save_file, "-W", save_file_fd,
+               "-c", scount, "-s", ssnap, "-S", 
+               "-m", medium_font, "-b", bold_font,
+               (cf.cfilter == NULL)? 0 : "-f",
+               (cf.cfilter == NULL)? 0 : cf.cfilter,
+               (const char *)NULL);    
+       }
+       else {
+        execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
+               "-w", cf.save_file, "-W", save_file_fd,
+               "-c", scount, "-s", ssnap,
+               "-m", medium_font, "-b", bold_font,
+               (cf.cfilter == NULL)? 0 : "-f",
+               (cf.cfilter == NULL)? 0 : cf.cfilter,
+               (const char *)NULL);
+       }
+    }
+    else {
+       cf.filename = cf.save_file;
+       if (sync_mode) {
+        close(sync_pipe[1]);
+
+        /* Read a byte count from "sync_pipe[0]", terminated with a
+           colon; if the count is 0, the child process created the
+           capture file and we should start reading from it, otherwise
+           the capture couldn't start and the count is a count of bytes
+           of error message, and we should display the message. */
+        byte_count = 0;
+        for (;;) {
+          i = read(sync_pipe[0], &c, 1);
+          if (i == 0) {
+            /* EOF - the child process died.
+               XXX - reap it and report the status. */
+            simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
+            return;
+          }
+          if (c == ';')
+            break;
+          if (!isdigit(c)) {
+            /* Child process handed us crap. */
+            simple_dialog(ESD_TYPE_WARN, NULL,
+               "Capture child process sent us a bad message");
+            return;
+          }
+          byte_count = byte_count*10 + c - '0';
+        }
+        if (byte_count == 0) {
+          /* Success. */
+          err = tail_cap_file(cf.save_file, &cf);
+          if (err != 0) {
+            simple_dialog(ESD_TYPE_WARN, NULL,
+                       file_open_error_message(err, FALSE), cf.save_file);
+          }
+        } else {
+          /* Failure. */
+          msg = g_malloc(byte_count + 1);
+          if (msg == NULL) {
+            simple_dialog(ESD_TYPE_WARN, NULL,
+               "Capture child process failed, but its error message was too big.");
+          } else {
+            i = read(sync_pipe[0], msg, byte_count);
+            if (i < 0) {
+               simple_dialog(ESD_TYPE_WARN, NULL,
+                 "Capture child process failed: Error %s reading its error message.",
+                 strerror(errno));
+            } else if (i == 0) {
+               simple_dialog(ESD_TYPE_WARN, NULL,
+                 "Capture child process failed: EOF reading its error message.");
+            } else
+               simple_dialog(ESD_TYPE_WARN, NULL, msg);
+            g_free(msg);
+          }
+        }
+       }
+    }
+  }
+  else
+    capture();
+}
+
+void
+capture(void)
+{
   GtkWidget  *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
              *ospf_lb, *gre_lb, *netbios_lb, *other_lb, *stop_bt;
   pcap_t     *pch;
@@ -106,8 +241,7 @@ capture(void) {
   bpf_u_int32 netnum, netmask;
   time_t      upd_time, cur_time;
   int         err, inpkts;
-  char       *errmsg;
-  char        errmsg_errno[1024+1];
+  char        errmsg[1024+1];
 
   ld.go             = TRUE;
   ld.counts.total   = 0;
@@ -127,250 +261,264 @@ capture(void) {
 
   pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str);
 
-  if (pch) {
-    ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
-    if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
-      errmsg = "The network you're capturing from is of a type"
-               " that Ethereal doesn't support.";
-      goto fail;
+  if (pch == NULL) {
+    /* Well, we couldn't start the capture. */
+    if (!fork_mode) {
+      /* In fork mode, we shouldn't do any UI stuff until we pop up the
+         capture-progress window, and, since we couldn't start the
+        capture, we haven't popped it up. */
+      while (gtk_events_pending()) gtk_main_iteration();
+    }
+    snprintf(errmsg, sizeof errmsg,
+      "The capture session could not be initiated (%s).\n"
+      "Please check to make sure you have sufficient permissions, and that\n"
+      "you have the proper interface specified.", err_str);
+    goto fatal_error;
+  }
+
+  if (cf.cfilter) {
+    if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
+      snprintf(errmsg, sizeof errmsg,
+        "Can't use filter:  Couldn't obtain netmask info (%s).", err_str);
+      goto fatal_error;
+    }
+    if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
+      snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
+       pcap_geterr(pch));
+      goto fatal_error;
     }
-    ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
+    if (pcap_setfilter(pch, &cf.fcode) < 0) {
+      snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
+       pcap_geterr(pch));
+      goto fatal_error;
+    }
+  }
+
+  ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
+  if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
+    strcpy(errmsg, "The network you're capturing from is of a type"
+             " that Ethereal doesn't support.");
+    goto fatal_error;
+  }
+  ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
                ld.linktype, pcap_snapshot(pch), &err);
 
-    if (ld.pdh == NULL) {  /* We have an error */
+  if (ld.pdh == NULL) {  /* We have an error */
+    switch (err) {
+
+    case WTAP_ERR_CANT_OPEN:
+      strcpy(errmsg, "The file to which the capture would be saved"
+               " couldn't be created for some unknown reason.");
+      break;
+
+    case WTAP_ERR_SHORT_WRITE:
+      strcpy(errmsg, "A full header couldn't be written to the file"
+               " to which the capture would be saved.");
+      break;
+
+    default:
+      if (err < 0) {
+        sprintf(errmsg, "The file to which the capture would be"
+                     " saved (\"%s\") could not be opened: Error %d.",
+                       cf.save_file, err);
+      } else {
+        sprintf(errmsg, "The file to which the capture would be"
+                     " saved (\"%s\") could not be opened: %s.",
+                       cf.save_file, strerror(err));
+      }
+      break;
+    }
+    goto fatal_error;
+  }
+
+  if (sync_mode) {
+    /* Sync out the capture file, so the header makes it to the file
+       system, and send a "capture started successfully and capture
+       file created" message to our parent so that they'll open the
+       capture file and update its windows to indicate that we have
+       a live capture in progress. */
+    fflush(wtap_dump_file(ld.pdh));
+    write(1, "0;", 2);
+  }
+
+  cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
+
+  /* Container for capture display widgets */
+  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_widget_show(main_vb);
+
+  count_lb = gtk_label_new("Count: 0");
+  gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
+  gtk_widget_show(count_lb);
+
+  tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
+  gtk_widget_show(tcp_lb);
+
+  udp_lb = gtk_label_new("UDP: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
+  gtk_widget_show(udp_lb);
+
+  icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
+  gtk_widget_show(icmp_lb);
+
+  ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
+  gtk_widget_show(ospf_lb);
+
+  gre_lb = gtk_label_new("GRE: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
+  gtk_widget_show(gre_lb);
+
+  netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
+  gtk_widget_show(netbios_lb);
+
+  other_lb = gtk_label_new("Other: 0 (0.0%)");
+  gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
+  gtk_widget_show(other_lb);
+
+  stop_bt = gtk_button_new_with_label ("Stop");
+  gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
+    GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
+  gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
+  GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(stop_bt);
+  GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(stop_bt);
+  gtk_widget_show(stop_bt);
+
+  gtk_widget_show(cap_w);
+  gtk_grab_add(cap_w);
+
+  upd_time = time(NULL);
+  while (ld.go) {
+    while (gtk_events_pending()) gtk_main_iteration();
+    inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+    if (inpkts > 0)
+      ld.sync_packets += inpkts;
+    /* Only update once a second so as not to overload slow displays */
+    cur_time = time(NULL);
+    if (cur_time > upd_time) {
+      upd_time = cur_time;
+
+      sprintf(label_str, "Count: %d", ld.counts.total);
+      gtk_label_set(GTK_LABEL(count_lb), label_str);
+
+      sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
+               pct(ld.counts.tcp, ld.counts.total));
+      gtk_label_set(GTK_LABEL(tcp_lb), label_str);
+
+      sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
+               pct(ld.counts.udp, ld.counts.total));
+      gtk_label_set(GTK_LABEL(udp_lb), label_str);
+
+      sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
+               pct(ld.counts.icmp, ld.counts.total));
+      gtk_label_set(GTK_LABEL(icmp_lb), label_str);
+
+      sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
+               pct(ld.counts.ospf, ld.counts.total));
+      gtk_label_set(GTK_LABEL(ospf_lb), label_str);
+
+      sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
+               pct(ld.counts.gre, ld.counts.total));
+      gtk_label_set(GTK_LABEL(gre_lb), label_str);
+
+      sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
+               pct(ld.counts.netbios, ld.counts.total));
+      gtk_label_set(GTK_LABEL(netbios_lb), label_str);
+
+      sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
+               pct(ld.counts.other, ld.counts.total));
+      gtk_label_set(GTK_LABEL(other_lb), label_str);
+
+      /* do sync here, too */
+      fflush(wtap_dump_file(ld.pdh));
+      if (sync_mode && ld.sync_packets) {
+       char tmp[20];
+       sprintf(tmp, "%d*", ld.sync_packets);
+       write(1, tmp, strlen(tmp));
+       ld.sync_packets = 0;
+      }
+    }
+  }
+    
+  if (ld.pdh) {
+    if (!wtap_dump_close(ld.pdh, &err)) {
       switch (err) {
 
-      case WTAP_ERR_CANT_OPEN:
-        errmsg = "The file to which the capture would be saved"
-                 " couldn't be created for some unknown reason.";
+      case WTAP_ERR_CANT_CLOSE:
+        strcpy(errmsg, "The file to which the capture was being saved"
+               " couldn't be closed for some unknown reason.");
         break;
 
       case WTAP_ERR_SHORT_WRITE:
-        errmsg = "A full header couldn't be written to the file"
-                 " to which the capture would be saved.";
+        strcpy(errmsg, "Not all the data could be written to the file"
+                 " to which the capture was being saved.");
         break;
 
       default:
         if (err < 0) {
-          sprintf(errmsg_errno, "The file to which the capture would be"
-                             " saved (\"%%s\") could not be opened: Error %d.",
-                               err);
+          sprintf(errmsg, "The file to which the capture was being"
+                     " saved (\"%s\") could not be closed: Error %d.",
+                       cf.save_file, err);
         } else {
-          sprintf(errmsg_errno, "The file to which the capture would be"
-                             " saved (\"%%s\") could not be opened: %s.",
-                               strerror(err));
+          sprintf(errmsg, "The file to which the capture was being"
+                     " saved (\"%s\") could not be closed: %s.",
+                       cf.save_file, strerror(err));
        }
-       errmsg = errmsg_errno;
        break;
       }
-fail:
-      snprintf(err_str, PCAP_ERRBUF_SIZE, errmsg, cf.save_file);
-      simple_dialog(ESD_TYPE_WARN, NULL, err_str);
-      pcap_close(pch);
-      return;
-    }
-
-    if (cf.cfilter) {
-      if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
-        simple_dialog(ESD_TYPE_WARN, NULL,
-          "Can't use filter:  Couldn't obtain netmask info (%s).", err_str);
-        wtap_dump_close(ld.pdh, NULL);
-        unlink(cf.save_file); /* silently ignore error */
-        pcap_close(pch);
-        return;
-      } else if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
-        simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string (%s).",
-                       pcap_geterr(pch));
-        wtap_dump_close(ld.pdh, NULL);
-        unlink(cf.save_file); /* silently ignore error */
-        pcap_close(pch);
-        return;
-      } else if (pcap_setfilter(pch, &cf.fcode) < 0) {
-        simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter (%s).",
-                       pcap_geterr(pch));
-        wtap_dump_close(ld.pdh, NULL);
-        unlink(cf.save_file); /* silently ignore error */
-        pcap_close(pch);
-        return;
-      }
-    }
-
-    if (sync_mode) {
-      /* Sync out the capture file, so the header makes it to the file
-         system, and signal our parent so that they'll open the capture
-        file and update its windows to indicate that we have a live
-        capture in progress. */
-      fflush(wtap_dump_file(ld.pdh));
-      kill(getppid(), SIGUSR2);
-    }
-
-    cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
-
-    /* Container for capture display widgets */
-    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_widget_show(main_vb);
-
-    count_lb = gtk_label_new("Count: 0");
-    gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
-    gtk_widget_show(count_lb);
-
-    tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
-    gtk_widget_show(tcp_lb);
-
-    udp_lb = gtk_label_new("UDP: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
-    gtk_widget_show(udp_lb);
-
-    icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
-    gtk_widget_show(icmp_lb);
-
-    ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
-    gtk_widget_show(ospf_lb);
-
-    gre_lb = gtk_label_new("GRE: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
-    gtk_widget_show(gre_lb);
-
-    netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
-    gtk_widget_show(netbios_lb);
-
-    other_lb = gtk_label_new("Other: 0 (0.0%)");
-    gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
-    gtk_widget_show(other_lb);
-
-    stop_bt = gtk_button_new_with_label ("Stop");
-    gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
-      GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
-    gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
-    GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
-    gtk_widget_grab_default(stop_bt);
-    GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
-    gtk_widget_grab_default(stop_bt);
-    gtk_widget_show(stop_bt);
-
-    gtk_widget_show(cap_w);
-    gtk_grab_add(cap_w);
-
-    upd_time = time(NULL);
-    while (ld.go) {
-      while (gtk_events_pending()) gtk_main_iteration();
-      inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
-      if (inpkts > 0)
-        ld.sync_packets += inpkts;
-      /* Only update once a second so as not to overload slow displays */
-      cur_time = time(NULL);
-      if (cur_time > upd_time) {
-
-        upd_time = cur_time;
-
-        sprintf(label_str, "Count: %d", ld.counts.total);
-        gtk_label_set(GTK_LABEL(count_lb), label_str);
-
-        sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
-          pct(ld.counts.tcp, ld.counts.total));
-        gtk_label_set(GTK_LABEL(tcp_lb), label_str);
-
-        sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
-         pct(ld.counts.udp, ld.counts.total));
-        gtk_label_set(GTK_LABEL(udp_lb), label_str);
-
-        sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
-         pct(ld.counts.icmp, ld.counts.total));
-        gtk_label_set(GTK_LABEL(icmp_lb), label_str);
-
-        sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
-         pct(ld.counts.ospf, ld.counts.total));
-        gtk_label_set(GTK_LABEL(ospf_lb), label_str);
-
-        sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
-         pct(ld.counts.gre, ld.counts.total));
-        gtk_label_set(GTK_LABEL(gre_lb), label_str);
-
-        sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
-         pct(ld.counts.netbios, ld.counts.total));
-        gtk_label_set(GTK_LABEL(netbios_lb), label_str);
-
-        sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
-          pct(ld.counts.other, ld.counts.total));
-        gtk_label_set(GTK_LABEL(other_lb), label_str);
-
-       /* do sync here, too */
-       fflush(wtap_dump_file(ld.pdh));
-       if (sync_mode && ld.sync_packets) {
-         char tmp[20];
-         sprintf(tmp, "%d*", ld.sync_packets);
-         write(1, tmp, strlen(tmp));
-         ld.sync_packets = 0;
-       }
-      }
-    }
-    
-    if (ld.pdh) {
-      if (!wtap_dump_close(ld.pdh, &err)) {
-        switch (err) {
-
-        case WTAP_ERR_CANT_CLOSE:
-          errmsg = "The file to which the capture was being saved"
-                 " couldn't be closed for some unknown reason.";
-          break;
-
-        case WTAP_ERR_SHORT_WRITE:
-          errmsg = "Not all the data could be written to the file"
-                   " to which the capture was being saved.";
-          break;
-
-        default:
-          if (err < 0) {
-            sprintf(errmsg_errno, "The file to which the capture was being"
-                             " saved (\"%%s\") could not be closed: Error %d.",
-                               err);
-          } else {
-            sprintf(errmsg_errno, "The file to which the capture was being"
-                             " saved (\"%%s\") could not be closed: %s.",
-                               strerror(err));
-         }
-         errmsg = errmsg_errno;
-         break;
-        }
-        snprintf(err_str, PCAP_ERRBUF_SIZE, errmsg, cf.save_file);
-        simple_dialog(ESD_TYPE_WARN, NULL, err_str);
-      }
+      goto error;
     }
-    pcap_close(pch);
-
-    gtk_grab_remove(GTK_WIDGET(cap_w));
-    gtk_widget_destroy(GTK_WIDGET(cap_w));
-  } else {
-    while (gtk_events_pending()) gtk_main_iteration();
-    simple_dialog(ESD_TYPE_WARN, NULL,
-      "The capture session could not be initiated (%s).\n"
-      "Please check to make sure you have sufficient permissions, and that\n"
-      "you have the proper interface specified.", err_str);
   }
+  pcap_close(pch);
+
+  gtk_grab_remove(GTK_WIDGET(cap_w));
+  gtk_widget_destroy(GTK_WIDGET(cap_w));
 
-  if( quit_after_cap ){
+  if (quit_after_cap) {
     /* DON'T unlink the save file.  Presumably someone wants it. */
     gtk_exit(0);
   }
 
-  if (pch) {
-    /* "pch" is non-NULL only if we successfully started a capture.
-       If we haven't, there's no capture file to load. */
-    if ((err = open_cap_file(cf.save_file, &cf)) == 0) {
-      /* Set the read filter to NULL. */
-      cf.rfcode = NULL;
-      err = read_cap_file(&cf);
-      set_menu_sensitivity("/File/Save", TRUE);
-      set_menu_sensitivity("/File/Save As...", FALSE);
-    }
+  if ((err = open_cap_file(cf.save_file, &cf)) == 0) {
+    /* Set the read filter to NULL. */
+    cf.rfcode = NULL;
+    err = read_cap_file(&cf);
+    set_menu_sensitivity("/File/Save", TRUE);
+    set_menu_sensitivity("/File/Save As...", FALSE);
+  }
+  return;
+
+fatal_error:
+  /* We couldn't even start the capture, so get rid of the capture
+     file. */
+  unlink(cf.save_file); /* silently ignore error */
+
+error:
+  if (sync_mode) {
+    /* Send the error message to our parent, so they can display a
+       dialog box containing it. */
+    int msglen = strlen(errmsg);
+    char lenbuf[10+1+1];
+    sprintf(lenbuf, "%u;", msglen);
+    write(1, lenbuf, strlen(lenbuf));
+    write(1, errmsg, msglen);
+  } else {
+    /* Display the dialog box ourselves; there's no parent. */
+    simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
   }
+  if (pch != NULL)
+    pcap_close(pch);
+
+  if (quit_after_cap)
+    gtk_exit(0);
 }
 
 static float
index 61cf251a966ea06930cb92503370b99162c9a186..52a23bf68f77cfed05c29b74b26af2553f12f223 100644 (file)
--- a/capture.h
+++ b/capture.h
@@ -1,7 +1,7 @@
 /* capture.h
  * Definitions for packet capture windows
  *
- * $Id: capture.h,v 1.14 1999/09/09 03:31:50 gram Exp $
+ * $Id: capture.h,v 1.15 1999/09/23 06:27:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -48,6 +48,7 @@
 #define DLT_PPP_BSDOS 14
 #endif
 
+void   do_capture(void);
 void   capture(void);
 
 #endif /* HAVE_LIBPCAP */
index 7bf742bd9fbeb4ac7a3161c18d1afb493c45c131..b3166d36b69cb5c81632cadc2bbfc67f45e713a9 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -1,7 +1,7 @@
 /* globals.h
  * Global defines, etc.
  *
- * $Id: globals.h,v 1.5 1999/09/19 15:54:53 deniel Exp $
+ * $Id: globals.h,v 1.6 1999/09/23 06:27:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -101,7 +101,6 @@ extern GtkStyle *item_style;
 extern int sync_mode;  /* allow sync */
 extern int sync_pipe[2]; /* used to sync father */
 extern int fork_mode;  /* fork a child to do the capture */
-extern int sigusr2_received;
 extern int quit_after_cap; /* Makes a "capture only mode". Implies -k */
 #endif
 
index 793556e815583634fb13baba63cf257202ea6fd5..6d4e1159e0a67215a0d050f3f4a6ea3b5458b49e 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_dlg.c
  * Routines for packet capture windows
  *
- * $Id: capture_dlg.c,v 1.2 1999/09/11 06:23:28 guy Exp $
+ * $Id: capture_dlg.c,v 1.3 1999/09/23 06:27:27 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -81,6 +81,7 @@
 #define E_CAP_COUNT_KEY "cap_count"
 #define E_CAP_OPEN_KEY  "cap_open"
 #define E_CAP_SNAP_KEY  "cap_snap"
+#define E_CAP_SYNC_KEY  "cap_sync"
 
 /* Capture filter key */
 #define E_CAP_FILT_TE_KEY "cap_filt_te"
@@ -106,7 +107,7 @@ capture_prep_cb(GtkWidget *w, gpointer d) {
                 *count_lb, *count_cb, *main_vb, *if_hb, *count_hb,
                 *filter_hb, *filter_bt, *filter_te, *caplen_hb,
                 *bbox, *ok_bt, *cancel_bt, *snap_lb,
-                *snap_sb;
+                *snap_sb, *sync_cb;
   GtkAdjustment *adj;
   GList         *if_list, *count_list = NULL;
   gchar         *count_item1 = "0 (Infinite)", count_item2[16];
@@ -205,6 +206,11 @@ capture_prep_cb(GtkWidget *w, gpointer d) {
   gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3); 
   gtk_widget_show(snap_sb);
   
+  sync_cb = gtk_check_button_new_with_label("Update list of packets in real time");
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), sync_mode);
+  gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
+  gtk_widget_show(sync_cb);
+  
   /* Button row: OK and cancel buttons */
   bbox = gtk_hbutton_box_new();
   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
@@ -232,30 +238,33 @@ capture_prep_cb(GtkWidget *w, gpointer d) {
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILT_KEY,  filter_te);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY,  snap_sb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY,  sync_cb);
 
   gtk_widget_show(cap_open_w);
 }
 
 static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
-  GtkWidget *if_cb, *filter_te, *count_cb, *snap_sb;
+  GtkWidget *if_cb, *filter_te, *count_cb, *snap_sb, *sync_cb;
   gchar *filter_text;
-  char tmpname[128+1];
 
   if_cb     = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IFACE_KEY);
   filter_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILT_KEY);
   count_cb  = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
   snap_sb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
+  sync_cb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
 
-  if (cf.iface) g_free(cf.iface);
+  if (cf.iface)
+    g_free(cf.iface);
   cf.iface =
     g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
 
   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
-  if (cf.cfilter) g_free(cf.cfilter);
+  if (cf.cfilter)
+    g_free(cf.cfilter);
   cf.cfilter = NULL; /* ead 06/16/99 */
   if (filter_text && filter_text[0]) {
-         cf.cfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te))); 
+    cf.cfilter = g_strdup(filter_text); 
   }
   cf.count = atoi(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));
@@ -263,87 +272,21 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
     cf.snap = WTAP_MAX_PACKET_SIZE;
   else if (cf.snap < MIN_PACKET_SIZE)
     cf.snap = MIN_PACKET_SIZE;
+  if (GTK_TOGGLE_BUTTON (sync_cb)->active) {
+    /* They requested that the summary window be updated as packets are
+       captured. */
+    sync_mode = TRUE;
+    fork_mode = TRUE; /* -S implies -F */
+  } else {
+    /* They requested that the summary window not be updated as packets are
+       captured. */
+    sync_mode = FALSE;
+    fork_mode = FALSE;
+  }
 
   gtk_widget_destroy(GTK_WIDGET(parent_w));
 
-  /* Choose a random name for the capture buffer */
-  if (cf.save_file && !cf.user_saved) {
-       unlink(cf.save_file); /* silently ignore error */
-       g_free(cf.save_file);
-  }
-  cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
-  cf.save_file = g_strdup(tmpname);
-  cf.user_saved = 0;
-  
-  if( fork_mode ){     /*  use fork() for capture */
-    int  fork_child;
-    char ssnap[24];
-    char scount[24];   /* need a constant for len of numbers */
-    char save_file_fd[24];
-    int err;
-
-    sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
-    sprintf(scount,"%d",cf.count);
-    sprintf(save_file_fd,"%d",cf.save_file_fd);
-    signal(SIGCHLD, SIG_IGN);
-    if (sync_mode) pipe(sync_pipe);
-    if((fork_child = fork()) == 0){
-      /* args: -k -- capture
-       * -i interface specification
-       * -w file to write
-       * -W file descriptor to write
-       * -c count to capture
-       * -Q quit after capture (forces -k)
-       * -s snaplen
-       * -S sync mode
-       * -m / -b fonts
-       * -f "filter expression"
-       */
-       if (sync_mode) {
-        close(1);
-        dup(sync_pipe[1]);
-        close(sync_pipe[0]);
-        execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
-               "-w", cf.save_file, "-W", save_file_fd,
-               "-c", scount, "-s", ssnap, "-S", 
-               "-m", medium_font, "-b", bold_font,
-               (cf.cfilter == NULL)? 0 : "-f",
-               (cf.cfilter == NULL)? 0 : cf.cfilter,
-               (const char *)NULL);    
-       }
-       else {
-        execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
-               "-w", cf.save_file, "-W", save_file_fd,
-               "-c", scount, "-s", ssnap,
-               "-m", medium_font, "-b", bold_font,
-               (cf.cfilter == NULL)? 0 : "-f",
-               (cf.cfilter == NULL)? 0 : cf.cfilter,
-               (const char *)NULL);
-       }
-    }
-    else {
-       cf.filename = cf.save_file;
-       if (sync_mode) {
-        close(sync_pipe[1]);
-        while (!sigusr2_received) {
-          struct timeval timeout = {1,0};
-          select(0, NULL, NULL, NULL, &timeout);
-          if (kill(fork_child, 0) == -1 && errno == ESRCH) 
-            break;
-        }
-        if (sigusr2_received) {
-          err = tail_cap_file(cf.save_file, &cf);
-          if (err != 0) {
-            simple_dialog(ESD_TYPE_WARN, NULL,
-                       file_open_error_message(err, FALSE), cf.save_file);
-          }
-        }
-        sigusr2_received = FALSE;
-       }
-    }
-  }
-  else
-    capture();
+  do_capture();
 }
 
 static void
index 50c9b15d56e1682b1011b2280c5c9fbd919df39d..3c1405c36fb1497ed941830c6c42566f7c626d94 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.6 1999/09/22 01:26:33 ashokn Exp $
+ * $Id: main.c,v 1.7 1999/09/23 06:27:27 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -118,7 +118,6 @@ GtkStyle *item_style;
 int sync_mode; /* allow sync */
 int sync_pipe[2]; /* used to sync father */
 int fork_mode; /* fork a child to do the capture */
-int sigusr2_received = 0;
 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
 #endif
 
@@ -444,14 +443,6 @@ main_realize_cb(GtkWidget *w, gpointer data) {
 #endif
 }
 
-#ifdef HAVE_LIBPCAP
-static void 
-sigusr2_handler(int sig) {
-  sigusr2_received = 1;
-  signal(SIGUSR2, sigusr2_handler);
-}
-#endif
-
 /* call initialization routines at program startup time */
 static void
 ethereal_proto_init(void) {
@@ -690,11 +681,6 @@ main(int argc, char *argv[])
 #endif
   }
 
-#ifdef HAVE_LIBPCAP
-  if (sync_mode)
-    signal(SIGUSR2, sigusr2_handler);
-#endif
-
   /* Build the column format array */  
   for (i = 0; i < cf.cinfo.num_cols; i++) {
     cf.cinfo.col_fmt[i] = get_column_format(i);