Change to color filters :
[obnox/wireshark/wip.git] / gtk / main.c
index 7f1e6b88bd27242152d848e33c159a8460987db9..05ae377df0df92b527d4492c03588ae1630d360e 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.253 2002/07/06 16:47:17 gerald Exp $
+ * $Id: main.c,v 1.264 2002/09/23 19:09:49 oabad Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -9,18 +9,18 @@
  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
  *                              needed by dissect routines
  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
- * 
- * 
+ *
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include <gtk/gtk.h>
 
-#include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <errno.h>
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
 #ifdef HAVE_IO_H
 #include <io.h> /* open/close on win32 */
 #endif
 
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include <signal.h>
-
 #ifdef HAVE_LIBPCAP
 #include <pcap.h>
 #endif
 #include "ui_util.h"
 #include "image/clist_ascend.xpm"
 #include "image/clist_descend.xpm"
+#include "../tap.h"
+#include "rpc_stat.h"
+#include "rpc_progs.h"
 
 #ifdef WIN32
 #include "capture-wpcap.h"
@@ -292,7 +269,7 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
 }
 
 void
-match_selected_cb_replace(GtkWidget *w, gpointer data)
+match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -301,7 +278,7 @@ match_selected_cb_replace(GtkWidget *w, gpointer data)
 }
 
 void
-match_selected_cb_and(GtkWidget *w, gpointer data)
+match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -310,7 +287,7 @@ match_selected_cb_and(GtkWidget *w, gpointer data)
 }
 
 void
-match_selected_cb_or(GtkWidget *w, gpointer data)
+match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -319,7 +296,7 @@ match_selected_cb_or(GtkWidget *w, gpointer data)
 }
 
 void
-match_selected_cb_not(GtkWidget *w, gpointer data)
+match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -328,7 +305,7 @@ match_selected_cb_not(GtkWidget *w, gpointer data)
 }
 
 void
-match_selected_cb_and_not(GtkWidget *w, gpointer data)
+match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -337,7 +314,7 @@ match_selected_cb_and_not(GtkWidget *w, gpointer data)
 }
 
 void
-match_selected_cb_or_not(GtkWidget *w, gpointer data)
+match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -346,7 +323,7 @@ match_selected_cb_or_not(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_replace(GtkWidget *w, gpointer data)
+prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -355,7 +332,7 @@ prepare_selected_cb_replace(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_and(GtkWidget *w, gpointer data)
+prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -364,7 +341,7 @@ prepare_selected_cb_and(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_or(GtkWidget *w, gpointer data)
+prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -373,7 +350,7 @@ prepare_selected_cb_or(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -382,7 +359,7 @@ prepare_selected_cb_not(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_and_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -391,7 +368,7 @@ prepare_selected_cb_and_not(GtkWidget *w, gpointer data)
 }
 
 void
-prepare_selected_cb_or_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
@@ -431,12 +408,12 @@ get_text_from_packet_list(gpointer data)
 
        epan_dissect_free(edt);
     }
-           
+
     return buf;
 }
 
 void
-match_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
@@ -444,7 +421,7 @@ match_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_and2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
@@ -452,7 +429,7 @@ match_selected_cb_and2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_or2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
@@ -460,7 +437,7 @@ match_selected_cb_or2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -468,7 +445,7 @@ match_selected_cb_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -476,7 +453,7 @@ match_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -484,7 +461,7 @@ match_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_REPLACE,
@@ -492,7 +469,7 @@ prepare_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_and2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND,
@@ -500,7 +477,7 @@ prepare_selected_cb_and2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_or2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR,
@@ -508,7 +485,7 @@ prepare_selected_cb_or2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_NOT,
@@ -516,7 +493,7 @@ prepare_selected_cb_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND_NOT,
@@ -524,7 +501,7 @@ prepare_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR_NOT,
@@ -542,10 +519,10 @@ filter_activate_cb(GtkWidget *w, gpointer data)
   gboolean   add_filter = TRUE;
   gboolean   free_filter = TRUE;
   char      *s;
-  
+
   g_assert(data);
   s = g_strdup(gtk_entry_get_text(GTK_ENTRY(data)));
-  
+
   /* GtkCombos don't let us get at their list contents easily, so we maintain
      our own filter list, and feed it to gtk_combo_set_popdown_strings when
      a new filter is added. */
@@ -592,9 +569,9 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
   /* Attempt to convert to numbers */
   double  num1 = atof(text1);
   double  num2 = atof(text2);
-  
+
   gint  col_fmt = cfile.cinfo.col_fmt[clist->sort_column];
-  
+
   if ((col_fmt == COL_NUMBER) || (col_fmt == COL_REL_TIME) || (col_fmt == COL_DELTA_TIME) ||
       ((col_fmt == COL_CLS_TIME) && (timestamp_type == RELATIVE)) ||
       ((col_fmt == COL_CLS_TIME) && (timestamp_type == DELTA))    ||
@@ -612,9 +589,9 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
     else
       return 0;
   }
-  
+
   else {
-    
+
     /* Compare text column */
     if (!text2)
       return (text1 != NULL);
@@ -627,19 +604,19 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
 }
 
 /* What to do when a column is clicked */
-static void 
+static void
 packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
 {
   column_arrows *col_arrows = (column_arrows *) data;
   int i;
-  
+
   gtk_clist_freeze(clist);
-  
+
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     gtk_widget_hide(col_arrows[i].ascend_pm);
     gtk_widget_hide(col_arrows[i].descend_pm);
   }
-  
+
   if (column == clist->sort_column) {
     if (clist->sort_type == GTK_SORT_ASCENDING) {
       clist->sort_type = GTK_SORT_DESCENDING;
@@ -660,7 +637,7 @@ packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
 }
 
 /* mark packets */
-static void 
+static void
 set_frame_mark(gboolean set, frame_data *frame, gint row) {
   GdkColor fg, bg;
 
@@ -670,19 +647,19 @@ set_frame_mark(gboolean set, frame_data *frame, gint row) {
     mark_frame(&cfile, frame);
     color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
     color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
   } else {
     unmark_frame(&cfile, frame);
-    fg = BLACK;
-    bg = WHITE;
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, NULL);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, NULL);
   }
   file_set_save_marked_sensitive();
-  gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
-  gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
 }
 
 static void
 packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_) {
-  
+
   GdkEventButton *event_button = (GdkEventButton *)event;
   gint row, column;
 
@@ -701,8 +678,8 @@ void mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
   if (cfile.current_frame) {
     /* XXX hum, should better have a "cfile->current_row" here ... */
     set_frame_mark(!cfile.current_frame->flags.marked,
-                  cfile.current_frame, 
-                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), 
+                  cfile.current_frame,
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
                                                cfile.current_frame));
   }
 }
@@ -712,7 +689,7 @@ static void mark_all_frames(gboolean set) {
   for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
     set_frame_mark(set,
                   fdata,
-                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));    
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
   }
 }
 
@@ -759,7 +736,9 @@ static void
 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_, gpointer user_data _U_)
 {
        field_info      *finfo;
-       gchar           *help_str = NULL, len_str[] = ", 65536 bytes    ";
+       gchar           *help_str = NULL;
+       gchar           len_str[2+10+1+5+1];    /* ", {N} bytes\0",
+                                                  N < 4294967296 */
        gboolean        has_blurb = FALSE;
        guint           length = 0, byte_len;
        GtkWidget       *byte_view;
@@ -779,7 +758,7 @@ tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_, gpointer
        set_menus_for_selected_tree_row(TRUE);
 
        if (finfo->hfinfo) {
-         if (finfo->hfinfo->blurb != NULL && 
+         if (finfo->hfinfo->blurb != NULL &&
              finfo->hfinfo->blurb[0] != '\0') {
            has_blurb = TRUE;
            length = strlen(finfo->hfinfo->blurb);
@@ -791,13 +770,13 @@ tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_, gpointer
          } else if (finfo->length == 1) {
            strcpy (len_str, ", 1 byte");
          } else {
-           sprintf (len_str, ", %d bytes", finfo->length);
+           snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
          }
          statusbar_pop_field_msg();    /* get rid of current help msg */
           if (length) {
            length += strlen(finfo->hfinfo->abbrev) + strlen(len_str) + 10;
            help_str = g_malloc(sizeof(gchar) * length);
-           sprintf(help_str, "%s (%s)%s", 
+           sprintf(help_str, "%s (%s)%s",
               (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
               finfo->hfinfo->abbrev, len_str);
            statusbar_push_field_msg(help_str);
@@ -835,7 +814,7 @@ tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
 {
        GtkWidget       *byte_view;
        const guint8    *data;
-       guint           len;    
+       guint           len;
 
        /*
         * Which byte view is displaying the current protocol tree
@@ -912,7 +891,7 @@ set_plist_sel_browse(gboolean val)
                gtk_clist_set_selection_mode(GTK_CLIST(packet_list), GTK_SELECTION_BROWSE);
        }
 }
-       
+
 /* Set the font of the packet list window. */
 void
 set_plist_font(GdkFont *font)
@@ -1072,13 +1051,13 @@ file_quit_cmd_cb (GtkWidget *widget _U_, gpointer data _U_)
        do_quit();
 }
 
-static void 
+static void
 print_usage(gboolean print_ver) {
 
   if (print_ver) {
     fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
          comp_info_str->str);
-  }  
+  }
 #ifdef HAVE_LIBPCAP
   fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
@@ -1099,7 +1078,7 @@ print_usage(gboolean print_ver) {
 #endif
 }
 
-static void 
+static void
 show_version(void)
 {
 #ifdef WIN32
@@ -1149,7 +1128,7 @@ get_positive_int(const char *string, const char *name)
 static gboolean
 set_autostop_criterion(const char *autostoparg)
 {
-  u_char *p, *colonp;
+  guchar *p, *colonp;
 
   colonp = strchr(autostoparg, ':');
   if (colonp == NULL)
@@ -1188,6 +1167,26 @@ set_autostop_criterion(const char *autostoparg)
 }
 #endif
 
+/* 
+   Once every 3 seconds we get a callback here which we use to update
+   the tap extensions. Since Gtk1 is single threaded we dont have to
+   worry about any locking or critical regions.
+ */
+static gint
+update_cb(gpointer data _U_)
+{
+       draw_tap_listeners(FALSE);
+       return 1;
+}
+void
+protect_thread_critical_region(void)
+{
+}
+void
+unprotect_thread_critical_region(void)
+{
+}
+
 /* And now our feature presentation... [ fade to music ] */
 int
 main(int argc, char *argv[])
@@ -1205,13 +1204,13 @@ main(int argc, char *argv[])
   extern char          pcap_version[];
 #endif /* HAVE_PCAP_VERSION */
 #endif /* HAVE_LIBPCAP */
-  
+
 #ifdef WIN32
-  WSADATA             wsaData; 
+  WSADATA             wsaData;
 #endif
 
   char                *gpf_path, *cf_path, *df_path;
-  const char          *pf_path;
+  char                *pf_path;
   int                  gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
   int                  err;
 #ifdef HAVE_LIBPCAP
@@ -1234,7 +1233,7 @@ main(int argc, char *argv[])
   gint                 desk_x, desk_y;
   gboolean             prefs_write_needed = FALSE;
 
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:v"
+#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:vz:"
 
 #ifdef HAVE_LIBPCAP
 #ifdef WIN32
@@ -1329,7 +1328,10 @@ main(int argc, char *argv[])
     exit(0);
   }
 
-  /* Set the current locale according to the program environment. 
+  /* this is to keep tap extensions updating once every 3 seconds */
+  gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
+
+  /* Set the current locale according to the program environment.
    * We haven't localized anything, but some GTK widgets are localized
    * (the file selection dialogue, for example).
    * This also sets the C-language locale to the native environment. */
@@ -1337,7 +1339,7 @@ main(int argc, char *argv[])
 
   /* Let GTK get its args */
   gtk_init (&argc, &argv);
-  
+
   /* Read the preference files. */
   prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
 
@@ -1382,26 +1384,7 @@ main(int argc, char *argv[])
   /* Read the display filter file. */
   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
 
-  /* Initialize the capture file struct */
-  cfile.plist          = NULL;
-  cfile.plist_end      = NULL;
-  cfile.wth            = NULL;
-  cfile.filename       = NULL;
-  cfile.user_saved     = FALSE;
-  cfile.is_tempfile    = FALSE;
-  cfile.rfcode         = NULL;
-  cfile.dfilter                = NULL;
-  cfile.dfcode         = NULL;
-#ifdef HAVE_LIBPCAP
-  cfile.cfilter                = g_strdup(EMPTY_FILTER);
-#endif
-  cfile.iface          = NULL;
-  cfile.save_file      = NULL;
-  cfile.save_file_fd   = -1;
-  cfile.has_snap       = FALSE;
-  cfile.snap           = WTAP_MAX_PACKET_SIZE;
-  cfile.count          = 0;
-  col_init(&cfile.cinfo, prefs->num_cols);
+  init_cap_file(&cfile);
 
   /* Assemble the compile-time options */
   comp_info_str = g_string_new("");
@@ -1465,7 +1448,7 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
         if (set_autostop_criterion(optarg) == FALSE) {
           fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
-          exit(1);          
+          exit(1);
         }
 #else
         capture_option_specified = TRUE;
@@ -1656,6 +1639,29 @@ main(int argc, char *argv[])
         cfile.save_file_fd = atoi(optarg);
        break;
 #endif
+        case 'z':
+            if(!strncmp(optarg,"rpc,",4)){
+              if(!strncmp(optarg,"rpc,rtt,",8)){
+                int rpcprogram, rpcversion;
+                if(sscanf(optarg,"rpc,rtt,%d,%d",&rpcprogram,&rpcversion)==2){
+                  gtk_rpcstat_init(rpcprogram,rpcversion);
+                } else {
+                  fprintf(stderr, "ethereal: invalid \"-z rpc,rtt,<program>,<version>\" argument\n");
+                  exit(1);
+                }
+              } else if(!strncmp(optarg,"rpc,programs",12)){
+                gtk_rpcprogs_init();
+              } else {
+                fprintf(stderr, "ethereal: invalid -z argument. Argument must be one of:\n");
+                fprintf(stderr, "   \"-z rpc,rtt,<program>,<version>\"\n");
+                fprintf(stderr, "   \"-z rpc,programs\"\n");
+                exit(1);
+              }
+            } else {
+              fprintf(stderr, "ethereal: invalid -z argument. Argument must be \"-z rpc,...\"\n");
+              exit(1);
+            }
+            break;
 
 #ifdef _WIN32
 #ifdef HAVE_LIBPCAP
@@ -1723,7 +1729,7 @@ main(int argc, char *argv[])
           sync_mode takes precedence;
        c) it makes no sense to enable the ring buffer if the maximum
           file size is set to "infinite". */
-    if (cfile.save_file == NULL) {
+    if (save_file == NULL) {
       fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
       capture_opts.ringbuffer_on = FALSE;
     }
@@ -1748,7 +1754,7 @@ main(int argc, char *argv[])
 
   /* Notify all registered modules that have had any of their preferences
      changed either from one of the preferences file or from the command
-     line that its preferences have changed. */
+     line that their preferences have changed. */
   prefs_apply_all();
 
 #ifndef HAVE_LIBPCAP
@@ -1769,12 +1775,12 @@ main(int argc, char *argv[])
         if_list = get_interface_list(&err, err_str);
         if (if_list == NULL) {
           switch (err) {
-  
+
           case CANT_GET_INTERFACE_LIST:
               fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
                        err_str);
               break;
-  
+
           case NO_INTERFACES_FOUND:
               fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
               break;
@@ -1796,7 +1802,8 @@ main(int argc, char *argv[])
   }
 #endif
 
-  /* Build the column format array */  
+  /* Build the column format array */
+  col_init(&cfile.cinfo, prefs->num_cols);
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     cfile.cinfo.col_fmt[i] = get_column_format(i);
     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
@@ -1819,14 +1826,14 @@ main(int argc, char *argv[])
     else if (capture_opts.snaplen < MIN_PACKET_SIZE)
       capture_opts.snaplen = MIN_PACKET_SIZE;
   }
-  
+
   /* Check the value range of the ringbuffer_num_files parameter */
   if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
     capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
   else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
     capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
 #endif
-  
+
   rc_file = get_persconffile_path(RC_FILE, FALSE);
   gtk_rc_parse(rc_file);
 
@@ -1924,6 +1931,8 @@ main(int argc, char *argv[])
              argument. */
           s = get_dirname(cf_name);
          set_last_open_dir(s);
+          g_free(cf_name);
+          cf_name = NULL;
         } else {
           if (rfcode != NULL)
             dfilter_free(rfcode);
@@ -1951,6 +1960,8 @@ main(int argc, char *argv[])
       simple_dialog(ESD_TYPE_WARN, NULL,
         "Could not open your preferences file\n\"%s\": %s.", pf_path,
         strerror(pf_open_errno));
+      g_free(pf_path);
+      pf_path = NULL;
   }
 
   /* If the user's capture filter file exists but we failed to open it,
@@ -1989,6 +2000,13 @@ main(int argc, char *argv[])
     if (start_capture) {
       /* "-k" was specified; start a capture. */
       do_capture(save_file);
+      if (save_file != NULL) {
+        /* Save the directory name for future file dialogs. */
+        s = get_dirname(save_file);  /* Overwrites save_file */
+        set_last_open_dir(s);
+        g_free(save_file);
+        save_file = NULL;
+      }
     }
     else {
       set_menus_for_capture_in_progress(FALSE);
@@ -2005,10 +2023,10 @@ main(int argc, char *argv[])
                 documentation correctly, gdk_window_get_deskrelative_origin applies
                 mainly to Enlightenment and gdk_window_get_root_origin applies for
                 all other WMs.
-          
+
           The code below tries both routines, and picks the one that returns
           the upper-left-most coordinates.
-          
+
           More info at:
 
           http://mail.gnome.org/archives/gtk-devel-list/2001-March/msg00289.html
@@ -2039,7 +2057,7 @@ main(int argc, char *argv[])
                                prefs_write_needed = TRUE;
                        }
                }
-               
+
                if (prefs->gui_geometry_save_size) {
                        if (top_level->window != NULL) {
                                /* XXX - Is this the "approved" method? */
@@ -2054,12 +2072,15 @@ main(int argc, char *argv[])
                                prefs_write_needed = TRUE;
                        }
                }
-               
+
                if (prefs_write_needed) {
                        write_prefs(&pf_path);
                }
+       } else {
+               /* Ignore errors silently */
+               g_free(pf_path);
        }
-       
+
   epan_cleanup();
   g_free(rc_file);
 
@@ -2191,7 +2212,7 @@ static const struct {
        { "bold",       "ultrabold" }
 };
 #define        N_WEIGHTS       (sizeof weight_map / sizeof weight_map[0])
-       
+
 char *
 boldify(const char *font_name)
 {
@@ -2263,11 +2284,11 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
        TRUE,
        TRUE
   };
-  
-  /* Main window */  
+
+  /* Main window */
   top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_widget_set_name(top_level, "main window");
-  gtk_signal_connect(GTK_OBJECT(top_level), "delete_event", 
+  gtk_signal_connect(GTK_OBJECT(top_level), "delete_event",
     GTK_SIGNAL_FUNC(main_window_delete_event_cb), NULL);
   gtk_signal_connect (GTK_OBJECT (top_level), "realize",
     GTK_SIGNAL_FUNC (window_icon_realize_cb), NULL);
@@ -2318,7 +2339,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
   gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
 
   col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * cfile.cinfo.num_cols);
-  
+
   set_plist_sel_browse(prefs->gui_plist_sel_browse);
   set_plist_font(m_r_font);
   gtk_widget_set_name(packet_list, "packet list");
@@ -2334,12 +2355,12 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 
     /* Right-justify the packet number column. */
     if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
-      gtk_clist_set_column_justification(GTK_CLIST(packet_list), i, 
+      gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
         GTK_JUSTIFY_RIGHT);
   }
   gtk_widget_set_usize(packet_list, -1, pl_size);
   gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
-                    GTK_SIGNAL_FUNC(popup_menu_handler), 
+                    GTK_SIGNAL_FUNC(popup_menu_handler),
                     gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
   gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
                     GTK_SIGNAL_FUNC(packet_list_button_pressed_cb), NULL);
@@ -2378,7 +2399,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     GTK_SIGNAL_FUNC(display_filter_construct_cb), &args);
   gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
   gtk_widget_show(filter_bt);
-  
+
   filter_cm = gtk_combo_new();
   filter_list = g_list_append (filter_list, "");
   gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
@@ -2454,7 +2475,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
        GTK_SHRINK, GTK_SHRINK, 0, 0);
     gtk_widget_show(column_lb);
     col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
-    gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 
+    gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm,
        1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
     if (i == 0) {
       gtk_widget_show(col_arrows[i].ascend_pm);
@@ -2480,7 +2501,10 @@ set_last_open_dir(char *dirname)
 
        if (dirname) {
                len = strlen(dirname);
-               if (dirname[len-1] != G_DIR_SEPARATOR) {
+               if (dirname[len-1] == G_DIR_SEPARATOR) {
+                       last_open_dir = g_strconcat(dirname, NULL);
+               }
+               else {
                        last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
                                NULL);
                }