aboutsummaryrefslogtreecommitdiffstats
path: root/filters.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-01-28 09:13:10 +0000
committerGuy Harris <guy@alum.mit.edu>2001-01-28 09:13:10 +0000
commitceef26d2c17d4ea94e1d323d2538f5488e734a92 (patch)
tree0da9239313e69f8834f9e0f21acc328ae614045f /filters.c
parent3c596f5d718465872676cdf4330d6174bc68342d (diff)
Have separate capture and display filter lists; some filter dialog boxes
use the capture filter lists, and others use the display filter list, as appropriate. Have separate menu items for editing the capture and display filter lists. Have separate "~/.ethereal/cfilters" and "~/.ethereal/dfilters" files for the two lists; if either of those files isn't found, we try "~/.ethereal/filters", which means that you will start out with two identical lists holding all your filters - if certain filters belong only in one list, you'll have to delete them by hand from the other list. Do I/O error checking when reading and writing filter lists; when writing a filter list, write it to a new file, and then rename the new file on top of the old file, so that you don't lose your old filter list if, for example, you run out of disk space or disk quota. svn path=/trunk/; revision=2948
Diffstat (limited to 'filters.c')
-rw-r--r--filters.c298
1 files changed, 261 insertions, 37 deletions
diff --git a/filters.c b/filters.c
index 682a37c9c7..2aeacbf1d6 100644
--- a/filters.c
+++ b/filters.c
@@ -1,7 +1,7 @@
/* filters.c
* Code for reading and writing the filters file.
*
- * $Id: filters.c,v 1.2 2001/01/28 04:52:28 guy Exp $
+ * $Id: filters.c,v 1.3 2001/01/28 09:13:07 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -46,44 +47,125 @@
#include "filters.h"
#include "util.h"
+/*
+ * Old filter file name.
+ */
+#define FILTER_FILE_NAME "filters"
+
+/*
+ * Capture filter file name.
+ */
+#define CFILTER_FILE_NAME "cfilters"
+
+/*
+ * Display filter file name.
+ */
+#define DFILTER_FILE_NAME "dfilters"
+
#define FILTER_LINE_SIZE 2048
/*
- * List of filters.
+ * List of capture filters.
+ */
+static GList *capture_filters = NULL;
+
+/*
+ * List of display filters.
*/
-GList *fl = NULL;
+static GList *display_filters = NULL;
+/*
+ * Read in a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
void
-get_filter_list(void)
+read_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return)
{
- GList *flp;
- filter_def *filt;
+ char *ff_path, *ff_dir = PF_DIR, *ff_name;
FILE *ff;
- gchar *ff_path, *ff_name = PF_DIR "/filters", f_buf[FILTER_LINE_SIZE];
- gchar *name_begin, *name_end, *filt_begin;
+ GList **flp;
+ GList *fl_ent;
+ filter_def *filt;
+ char f_buf[FILTER_LINE_SIZE];
+ char *name_begin, *name_end, *filt_begin;
int len, line = 0;
- /* If we already have a list of filters, discard it. */
- if (fl != NULL) {
- flp = g_list_first(fl);
- while (flp) {
- filt = (filter_def *) flp->data;
- g_free(filt->name);
- g_free(filt->strval);
- g_free(filt);
- flp = flp->next;
- }
- g_list_free(fl);
- fl = NULL;
+ *pref_path_return = NULL; /* assume no error */
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ ff_name = CFILTER_FILE_NAME;
+ flp = &capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ ff_name = DFILTER_FILE_NAME;
+ flp = &display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ return;
}
/* To do: generalize this */
- ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_name) + 4);
- sprintf(ff_path, "%s/%s", get_home_dir(), ff_name);
+ ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +
+ strlen(ff_name) + 4);
+ sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
if ((ff = fopen(ff_path, "r")) == NULL) {
- g_free(ff_path);
- return;
+ /*
+ * Did that fail because we the file didn't exist?
+ */
+ if (errno != ENOENT) {
+ /*
+ * No. Just give up.
+ */
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ return;
+ }
+
+ /*
+ * Yes. See if there's a "filters" file; if so, read it.
+ * This means that a user will start out with their capture and
+ * display filter lists being identical; each list may contain
+ * filters that don't belong in that list. The user can edit
+ * the filter lists, and delete the ones that don't belong in
+ * a particular list.
+ */
+ sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, FILTER_FILE_NAME);
+ if ((ff = fopen(ff_path, "r")) == NULL) {
+ /*
+ * Well, that didn't work, either. Just give up.
+ * Return an error if the file existed but we couldn't open it.
+ */
+ if (errno != ENOENT) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ }
+ return;
+ }
+ }
+
+ /* If we already have a list of filters, discard it. */
+ if (*flp != NULL) {
+ fl_ent = g_list_first(*flp);
+ while (fl_ent != NULL) {
+ filt = (filter_def *) fl_ent->data;
+ g_free(filt->name);
+ g_free(filt->strval);
+ g_free(filt);
+ fl_ent = fl_ent->next;
+ }
+ g_list_free(*flp);
+ *flp = NULL;
}
while (fgets(f_buf, FILTER_LINE_SIZE, ff)) {
@@ -115,23 +197,130 @@ get_filter_list(void)
filt = (filter_def *) g_malloc(sizeof(filter_def));
filt->name = g_strdup(name_begin);
filt->strval = g_strdup(filt_begin);
- fl = g_list_append(fl, filt);
+ *flp = g_list_append(*flp, filt);
}
+ if (ferror(ff)) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ } else
+ g_free(ff_path);
fclose(ff);
- g_free(ff_path);
}
+/*
+ * Get a pointer to a list of filters.
+ */
+static GList **
+get_filter_list(filter_list_type_t list)
+{
+ GList **flp;
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ flp = &capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ flp = &display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ flp = NULL;
+ }
+ return flp;
+}
+
+/*
+ * Get a pointer to the first entry in a filter list.
+ */
+GList *
+get_filter_list_first(filter_list_type_t list)
+{
+ GList **flp;
+
+ flp = get_filter_list(list);
+ return g_list_first(*flp);
+}
+
+/*
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
+ */
+GList *
+add_to_filter_list(filter_list_type_t list, char *name, char *expression)
+{
+ GList **flp;
+ filter_def *filt;
+
+ flp = get_filter_list(list);
+ filt = (filter_def *) g_malloc(sizeof(filter_def));
+ filt->name = g_strdup(name);
+ filt->strval = g_strdup(expression);
+ *flp = g_list_append(*flp, filt);
+ return g_list_last(*flp);
+}
+
+/*
+ * Remove a filter from a list.
+ */
+void
+remove_from_filter_list(filter_list_type_t list, GList *fl_entry)
+{
+ GList **flp;
+ filter_def *filt;
+
+ flp = get_filter_list(list);
+ filt = (filter_def *) fl_entry->data;
+ g_free(filt->name);
+ g_free(filt->strval);
+ g_free(filt);
+ *flp = g_list_remove_link(*flp, fl_entry);
+}
+
+/*
+ * Write out a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
void
-save_filter_list(void)
+save_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return)
{
+ gchar *ff_path, *ff_path_new, *ff_dir = PF_DIR, *ff_name;
+ int path_length;
+ GList *fl;
GList *flp;
filter_def *filt;
- gchar *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
FILE *ff;
struct stat s_buf;
- ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +
- strlen(ff_name) + 4);
+ *pref_path_return = NULL; /* assume no error */
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ ff_name = CFILTER_FILE_NAME;
+ fl = capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ ff_name = DFILTER_FILE_NAME;
+ fl = display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ return;
+ }
+
+ path_length = strlen(get_home_dir()) + strlen(ff_dir) + strlen(ff_name)
+ + 4 + 4;
+ ff_path = (gchar *) g_malloc(path_length);
sprintf(ff_path, "%s/%s", get_home_dir(), ff_dir);
if (stat(ff_path, &s_buf) != 0)
@@ -143,15 +332,50 @@ save_filter_list(void)
sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
- if ((ff = fopen(ff_path, "w")) != NULL) {
- flp = g_list_first(fl);
- while (flp) {
- filt = (filter_def *) flp->data;
- fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
- flp = flp->next;
+ /* Write to "XXX.new", and rename if that succeeds.
+ That means we don't trash the file if we fail to write it out
+ completely. */
+ ff_path_new = (gchar *) g_malloc(path_length);
+ sprintf(ff_path_new, "%s/%s/%s.new", get_home_dir(), ff_dir, ff_name);
+
+ if ((ff = fopen(ff_path_new, "w")) == NULL) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ g_free(ff_path_new);
+ return;
+ }
+ flp = g_list_first(fl);
+ while (flp) {
+ filt = (filter_def *) flp->data;
+ fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
+ if (ferror(ff)) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ fclose(ff);
+ unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
}
- fclose(ff);
+ flp = flp->next;
+ }
+ if (fclose(ff) == EOF) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
}
+ /* XXX - does "rename()" exist on Win32? If so, does it remove the
+ target first? If so, does that mean it's not atomic? */
+ if (rename(ff_path_new, ff_path) < 0) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ unlink(ff_path_new);
+ g_free(ff_path);
+ g_free(ff_path_new);
+ return;
+ }
+ g_free(ff_path_new);
g_free(ff_path);
}