The dfilter yacc grammar now keeps track of every GNode that it allocates.
[obnox/wireshark/wip.git] / ethereal.c
index 7e963373893c626c3b0cac83f0d77d151e94baf1..cf342c03d71b380bec61822a2c5227742efc1f5a 100644 (file)
@@ -1,6 +1,6 @@
 /* ethereal.c
  *
- * $Id: ethereal.c,v 1.92 1999/08/17 00:10:22 guy Exp $
+ * $Id: ethereal.c,v 1.108 1999/08/26 06:20:49 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -88,7 +88,6 @@
 #include "summary.h"
 #include "file.h"
 #include "menu.h"
-#include "etypes.h"
 #include "prefs.h"
 #include "column.h"
 #include "print.h"
@@ -171,7 +170,7 @@ about_ethereal( GtkWidget *w, gpointer data ) {
                "Johan Feyaerts           <Johan.Feyaerts@siemens.atea.be>\n"
                "Olivier Abad             <abad@daba.dhis.org>\n"
                "Thierry Andry            <Thierry.Andry@advalvas.be>\n"
-               "Jeff Foster              <jjfoste@woodward.com>\n"
+               "Jeff Foster              <jfoste@woodward.com>\n"
 
                "\nSee http://ethereal.zing.org for more information",
                 VERSION, comp_info_str);
@@ -191,14 +190,10 @@ file_progress_cb(gpointer p) {
    selected packet, or it might be the last packet in the file). */
 void
 follow_stream_cb( GtkWidget *w, gpointer data ) {
-  char filename1[128];
+  char      filename1[128+1];
   GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
-  GtkWidget *filter_te = NULL;
   int        tmp_fd;
 
-  if (w)
-       filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
-
   if( pi.ipproto == 6 ) {
     /* we got tcp so we can follow */
     /* Create a temporary file into which to dump the reassembled data
@@ -209,12 +204,10 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
        append stuff to the text widget for the TCP stream window,
        if we can arrange that said window not pop up until we're
        done. */
-    snprintf( filename1, sizeof filename1, "%sXXXXXXXXXX", P_tmpdir );
-    tmp_fd = mkstemp( filename1 );
+    tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
     if (tmp_fd == -1) {
       simple_dialog(ESD_TYPE_WARN, NULL,
         "Could not create temporary file %s: %s", filename1, strerror(errno));
-      unlink(filename1);
       return;
     }
     data_out_file = fdopen( tmp_fd, "w" );
@@ -226,23 +219,17 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
       return;
     }
 
-    /* Delete any display filter we currently have. */
-    if( cf.dfilter != NULL ) {
-      /* get rid of this one */
-      g_free( cf.dfilter );
-      cf.dfilter = NULL;
-    }
-
     /* Create a new filter that matches all packets in the TCP stream,
        and set the display filter entry accordingly */
     reset_tcp_reassembly();
     cf.dfilter = build_follow_filter( &pi );
-    if (filter_te)
-           gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
+
     /* Run the display filter so it goes in effect. */
     filter_packets(&cf);
+
     /* the data_out_file should now be full of the streams information */
     fclose( data_out_file );
+
     /* the filename1 file now has all the text that was in the session */
     streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
     gtk_widget_set_name( streamwindow, "TCP stream window" );
@@ -259,15 +246,18 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
     }
     gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
     gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
+
     /* setup the container */
     box = gtk_vbox_new( FALSE, 0 );
     gtk_container_add( GTK_CONTAINER(streamwindow), box );
     gtk_widget_show( box );
+
     /* set up the table we attach to */
     table = gtk_table_new( 1, 2, FALSE );
     gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
     gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
     gtk_widget_show( table );
+
     /* create a text box */
     text = gtk_text_new( NULL, NULL );
     gtk_text_set_editable( GTK_TEXT(text), FALSE);
@@ -275,12 +265,14 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
                      GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                      GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
     gtk_widget_show(text);
+
     /* create the scrollbar */
     vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
     gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
                      GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
     gtk_widget_show( vscrollbar );
     gtk_widget_realize( text );
+
     /* stop the updates while we fill the text box */
     gtk_text_freeze( GTK_TEXT(text) );
     data_out_file = fopen( filename1, "r" );
@@ -307,10 +299,6 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
     unlink( filename1 );
     data_out_file = NULL;
     gtk_widget_show( streamwindow );
-    if( cf.dfilter != NULL ) {
-      g_free( cf.dfilter );
-      cf.dfilter = NULL;
-    }
   } else {
     simple_dialog(ESD_TYPE_WARN, NULL,
       "Error following stream.  Please make\n"
@@ -328,7 +316,6 @@ match_selected_cb(GtkWidget *w, gpointer data)
     int i;
     guint8 *c;
 
-    if (w)
     filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
 
     if (tree_selected_start<0) {
@@ -339,26 +326,12 @@ match_selected_cb(GtkWidget *w, gpointer data)
        return;
     }
 
-/*    sprintf(buf, "("); ptr = buf+strlen(buf);
-    for (i=0, c=cf.pd+tree_selected_start; i+4<tree_selected_len; i+=4, c+=4) {
-       sprintf(ptr, "(frame[%d : 4]=0x%02X%02X%02X%02X) and ", 
-              tree_selected_start+i, 
-              *c,
-              *(c+1),
-              *(c+2),
-              *(c+3));
-       ptr = buf+strlen(buf);
-    }*/
-
-    i = 0;
     c = cf.pd + tree_selected_start;
     ptr = buf;
 
-    sprintf(ptr, "frame[%d : %d] == ", 
-          tree_selected_start+i, 
-          tree_selected_len - i);
+    sprintf(ptr, "frame[%d : %d] == ", tree_selected_start, tree_selected_len);
     ptr = buf+strlen(buf);
-    /*for (;i<tree_selected_len; i++) {*/
+
     if (tree_selected_len == 1) {
         sprintf(ptr, "0x%02x", *c++);
     }
@@ -374,22 +347,17 @@ match_selected_cb(GtkWidget *w, gpointer data)
            }
     }
 
-    /*sprintf(ptr, "))");*/
     if( cf.dfilter != NULL ) {
       /* get rid of this one */
       g_free( cf.dfilter );
-      cf.dfilter = NULL;
     }
     /* create a new one and set the display filter entry accordingly */
     cf.dfilter = buf;
-    if (filter_te)
+    if (filter_te) {
        gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
+    }
     /* Run the display filter so it goes in effect. */
     filter_packets(&cf);
-    if( cf.dfilter != NULL ) {
-      g_free( cf.dfilter );
-      cf.dfilter = NULL;
-    }
 }
 
 /* Open a file */
@@ -460,8 +428,7 @@ file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
   if (rfilter[0] != '\0') {
        rfcode = dfilter_new();
        if (dfilter_compile(rfcode, rfilter) != 0) {
-               simple_dialog(ESD_TYPE_WARN, NULL,
-                   "Unable to parse filter string \"%s\".", rfilter);
+               simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
                dfilter_destroy(rfcode);
                return;
        }
@@ -487,27 +454,25 @@ file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
   gtk_widget_hide(GTK_WIDGET (fs));
   gtk_widget_destroy(GTK_WIDGET (fs));
 
-  if ((err = read_cap_file(&cf)) == 0) {
-         /* The read succeeded.  Save the directory name; we can
-            write over cf_name. */
-         s = strrchr(cf_name, '/');
-         if (s && last_open_dir) {
-                 *s = '\0';
-                 if (strcmp(last_open_dir, cf_name) != 0) {
-                         g_free(last_open_dir);
-                         last_open_dir = g_strdup(cf_name);
-                 }
-         }
-         else if (s) { /* ! last_open_dir */
-                 *s = '\0';
+  err = read_cap_file(&cf);
+  /* Save the directory name; we can write over cf_name. */
+  s = strrchr(cf_name, '/');
+  if (s && last_open_dir) {
+         *s = '\0';
+         if (strcmp(last_open_dir, cf_name) != 0) {
+                 g_free(last_open_dir);
                  last_open_dir = g_strdup(cf_name);
          }
-         else {
-                 last_open_dir = NULL;
-         }
-         set_menu_sensitivity("/File/Save", FALSE);
-         set_menu_sensitivity("/File/Save As...", TRUE);
   }
+  else if (s) { /* ! last_open_dir */
+         *s = '\0';
+         last_open_dir = g_strdup(cf_name);
+  }
+  else {
+         last_open_dir = NULL;
+  }
+  set_menu_sensitivity("/File/Save", FALSE);
+  set_menu_sensitivity("/File/Save As...", TRUE);
   g_free(cf_name);
 }
 
@@ -538,7 +503,7 @@ file_save_cmd_cb(GtkWidget *w, gpointer data) {
 
 void
 file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
-  file_sel = gtk_file_selection_new ("Ethereal: Save Capture File as");
+  file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
 
   /* Connect the ok_button to file_save_as_ok_cb function and pass along a
      pointer to the file selection box widget */
@@ -569,8 +534,8 @@ file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        g_free(cf.save_file);
        cf.save_file = g_strdup(cf_name);
        cf.user_saved = 1;
-        if ((err = open_cap_file(cf_name, &cf)) == 0 &&
-           (err = read_cap_file(&cf)) == 0) {
+        if ((err = open_cap_file(cf_name, &cf)) == 0) {
+               err = read_cap_file(&cf);
                set_menu_sensitivity("/File/Save", FALSE);
                set_menu_sensitivity("/File/Save As...", TRUE);
        }
@@ -589,8 +554,8 @@ file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        g_free(cf.filename);
        cf.filename = g_strdup(cf_name);
        cf.user_saved = 1;
-        if ((err = open_cap_file(cf.filename, &cf)) == 0 &&
-           (err = read_cap_file(&cf)) == 0) {
+        if ((err = open_cap_file(cf.filename, &cf)) == 0) {
+               err = read_cap_file(&cf);
                set_menu_sensitivity("/File/Save", FALSE);
                set_menu_sensitivity("/File/Save As...", TRUE);
        }
@@ -608,7 +573,7 @@ file_reload_cmd_cb(GtkWidget *w, gpointer data) {
   cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
   if (open_cap_file(cf.filename, &cf) == 0)
     read_cap_file(&cf);
-  /* XXX - change the menu if it fails? */
+  /* XXX - change the menu if the open fails? */
 }
 
 /* Run the current display filter on the current packet set, and
@@ -1043,6 +1008,12 @@ ethereal_proto_init(void) {
   dfilter_init();
 }
 
+static void
+ethereal_proto_cleanup(void) {
+       proto_cleanup();
+       dfilter_cleanup();
+}
+
 static void 
 print_usage(void) {
 
@@ -1124,8 +1095,9 @@ main(int argc, char *argv[])
 #endif
   cf.iface             = NULL;
   cf.save_file         = NULL;
+  cf.save_file_fd      = -1;
   cf.user_saved                = 0;
-  cf.snap              = MAX_PACKET_SIZE;
+  cf.snap              = WTAP_MAX_PACKET_SIZE;
   cf.count             = 0;
   cf.cinfo.num_cols    = prefs->num_cols;
   cf.cinfo.col_fmt      = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
@@ -1151,7 +1123,7 @@ main(int argc, char *argv[])
 
 #ifndef WIN32
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:v")) != EOF) {
+  while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
     switch (opt) {
       case 'b':               /* Bold font */
        bold_font = g_strdup(optarg);
@@ -1235,9 +1207,12 @@ main(int argc, char *argv[])
         exit(0);
         break;
 #ifdef HAVE_LIBPCAP
-      case 'w':        /* Write capture file xxx */
+      case 'w':        /* Write to capture file xxx */
         cf.save_file = g_strdup(optarg);
        break;
+      case 'W':        /* Write to capture file FD xxx */
+        cf.save_file_fd = atoi(optarg);
+       break;
 #endif
     }
   }
@@ -1252,6 +1227,15 @@ main(int argc, char *argv[])
       fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-w\" flag\n");
       exit(1);
     }
+#ifdef HAVE_LIBPCAP
+    if (fork_mode) {
+      if (cf.save_file_fd == -1) {
+        fprintf(stderr, "ethereal: \"-k\" flag was specified with \"-%c\" flag but without \"-W\" flag\n",
+            (sync_mode ? 'S' : 'F'));
+        exit(1);
+      }
+    }
+#endif
   }
 
 #ifdef HAVE_LIBPCAP
@@ -1272,7 +1256,7 @@ main(int argc, char *argv[])
   }
 
   if (cf.snap < 1)
-    cf.snap = MAX_PACKET_SIZE;
+    cf.snap = WTAP_MAX_PACKET_SIZE;
   else if (cf.snap < MIN_PACKET_SIZE)
     cf.snap = MIN_PACKET_SIZE;
   
@@ -1429,10 +1413,14 @@ main(int argc, char *argv[])
     GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
   gtk_widget_show(filter_te);
 
+  /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
+   * of any widget that ends up calling a callback which needs
+   * that text entry pointer */
   set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
   set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
+  set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY,
     filter_te);
+
   info_bar = gtk_statusbar_new();
   main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
   file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
@@ -1448,9 +1436,11 @@ main(int argc, char *argv[])
 
   gtk_widget_show(window);
 
+  colors_init(&cf);
+
   /* If we were given the name of a capture file, read it in now;
      we defer it until now, so that, if we can't open it, and pop
-     up an alert box, the alert box is more likely to cmoe up on
+     up an alert box, the alert box is more likely to come up on
      top of the main window - but before the preference-file-error
      alert box, so, if we get one of those, it's more likely to come
      up on top of us. */
@@ -1458,17 +1448,15 @@ main(int argc, char *argv[])
     if (rfilter != NULL) {
       rfcode = dfilter_new();
       if (dfilter_compile(rfcode, rfilter) != 0) {
-        simple_dialog(ESD_TYPE_WARN, NULL,
-           "Unable to parse filter string \"%s\".", rfilter);
+        simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
         dfilter_destroy(rfcode);
         rfilter_parse_failed = TRUE;
       }
     }
     if (!rfilter_parse_failed) {
-      cf.rfcode = rfcode;
-      if ((err = open_cap_file(cf_name, &cf)) == 0)
+      if ((err = open_cap_file(cf_name, &cf)) == 0) {
+        cf.rfcode = rfcode;
         err = read_cap_file(&cf);
-      if (err == 0) {
         s = strrchr(cf_name, '/');
         if (s) {
           last_open_dir = cf_name;
@@ -1484,11 +1472,13 @@ main(int argc, char *argv[])
      come up on top of the main window. */
   if (pf_path != NULL) {
       simple_dialog(ESD_TYPE_WARN, NULL,
-        "Can't open preferences file\n\"%s\": %s.", pf_path,
+        "Could not open preferences file\n\"%s\": %s.", pf_path,
         strerror(pf_open_errno));
   }
 
   gtk_main();
 
+  ethereal_proto_cleanup();
+
   exit(0);
 }