2 * Code for reading and writing the filters file.
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #include <epan/filesystem.h>
45 * Old filter file name.
47 #define FILTER_FILE_NAME "filters"
50 * Capture filter file name.
52 #define CFILTER_FILE_NAME "cfilters"
55 * Display filter file name.
57 #define DFILTER_FILE_NAME "dfilters"
60 * List of capture filters.
62 static GList *capture_filters = NULL;
65 * List of display filters.
67 static GList *display_filters = NULL;
70 * Read in a list of filters.
72 * On success, "*pref_path_return" is set to NULL.
73 * On error, "*pref_path_return" is set to point to the pathname of
74 * the file we tried to read - it should be freed by our caller -
75 * and "*errno_return" is set to the error.
78 #define INIT_BUF_SIZE 128
81 read_filter_list(filter_list_type_t list, char **pref_path_return,
84 char *ff_path, *ff_name;
90 char *filt_name, *filt_expr;
91 int filt_name_len, filt_expr_len;
92 int filt_name_index, filt_expr_index;
95 *pref_path_return = NULL; /* assume no error */
100 ff_name = CFILTER_FILE_NAME;
101 flp = &capture_filters;
105 ff_name = DFILTER_FILE_NAME;
106 flp = &display_filters;
110 g_assert_not_reached();
114 /* try to open personal "cfilters"/"dfilters" file */
115 ff_path = get_persconffile_path(ff_name, FALSE);
116 if ((ff = fopen(ff_path, "r")) == NULL) {
118 * Did that fail because the file didn't exist?
120 if (errno != ENOENT) {
124 *pref_path_return = ff_path;
125 *errno_return = errno;
130 * Yes. See if there's an "old style" personal "filters" file; if so, read it.
131 * This means that a user will start out with their capture and
132 * display filter lists being identical; each list may contain
133 * filters that don't belong in that list. The user can edit
134 * the filter lists, and delete the ones that don't belong in
138 ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE);
139 if ((ff = fopen(ff_path, "r")) == NULL) {
141 * Did that fail because the file didn't exist?
143 if (errno != ENOENT) {
147 *pref_path_return = ff_path;
148 *errno_return = errno;
153 * Try to open the global "cfilters/dfilters" file */
154 ff_path = get_datafile_path(ff_name);
155 if ((ff = fopen(ff_path, "r")) == NULL) {
158 * Well, that didn't work, either. Just give up.
159 * Return an error if the file existed but we couldn't open it.
161 if (errno != ENOENT) {
162 *pref_path_return = ff_path;
163 *errno_return = errno;
170 /* If we already have a list of filters, discard it. */
172 fl_ent = g_list_first(*flp);
173 while (fl_ent != NULL) {
174 filt = (filter_def *) fl_ent->data;
176 g_free(filt->strval);
178 fl_ent = fl_ent->next;
184 /* Allocate the filter name buffer. */
185 filt_name_len = INIT_BUF_SIZE;
186 filt_name = g_malloc(filt_name_len + 1);
187 filt_expr_len = INIT_BUF_SIZE;
188 filt_expr = g_malloc(filt_expr_len + 1);
190 for (line = 1; ; line++) {
191 /* Lines in a filter file are of the form
195 where "name" is a name, in quotes - backslashes in the name
196 escape the next character, so quotes and backslashes can appear
197 in the name - and "expression" is a filter expression, not in
198 quotes, running to the end of the line. */
200 /* Skip over leading white space, if any. */
201 while ((c = getc(ff)) != EOF && isspace(c)) {
209 break; /* Nothing more to read */
211 /* "c" is the first non-white-space character.
212 If it's not a quote, it's an error. */
214 g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path,
217 c = getc(ff); /* skip to the end of the line */
221 /* Get the name of the filter. */
225 if (c == EOF || c == '\n')
226 break; /* End of line - or end of file */
229 if (filt_name_index >= filt_name_len) {
230 /* Filter name buffer isn't long enough; double its length. */
232 filt_name = g_realloc(filt_name, filt_name_len + 1);
234 filt_name[filt_name_index] = '\0';
238 /* Next character is escaped */
240 if (c == EOF || c == '\n')
241 break; /* End of line - or end of file */
243 /* Add this character to the filter name string. */
244 if (filt_name_index >= filt_name_len) {
245 /* Filter name buffer isn't long enough; double its length. */
247 filt_name = g_realloc(filt_name, filt_name_len + 1);
249 filt_name[filt_name_index] = c;
255 /* EOF, not error; no newline seen before EOF */
256 g_warning("'%s' line %d doesn't have a newline.", ff_path,
259 break; /* nothing more to read */
263 /* No newline seen before end-of-line */
264 g_warning("'%s' line %d doesn't have a closing quote.", ff_path,
269 /* Skip over separating white space, if any. */
270 while ((c = getc(ff)) != EOF && isspace(c)) {
277 /* EOF, not error; no newline seen before EOF */
278 g_warning("'%s' line %d doesn't have a newline.", ff_path,
281 break; /* nothing more to read */
285 /* No filter expression */
286 g_warning("'%s' line %d doesn't have a filter expression.", ff_path,
291 /* "c" is the first non-white-space character; it's the first
292 character of the filter expression. */
295 /* Add this character to the filter expression string. */
296 if (filt_expr_index >= filt_expr_len) {
297 /* Filter expressioin buffer isn't long enough; double its length. */
299 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
301 filt_expr[filt_expr_index] = c;
304 /* Get the next character. */
306 if (c == EOF || c == '\n')
312 /* EOF, not error; no newline seen before EOF */
313 g_warning("'%s' line %d doesn't have a newline.", ff_path,
316 break; /* nothing more to read */
319 /* We saw the ending newline; terminate the filter expression string */
320 if (filt_expr_index >= filt_expr_len) {
321 /* Filter expressioin buffer isn't long enough; double its length. */
323 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
325 filt_expr[filt_expr_index] = '\0';
327 /* Add the new filter to the list of filters */
328 filt = (filter_def *) g_malloc(sizeof(filter_def));
329 filt->name = g_strdup(filt_name);
330 filt->strval = g_strdup(filt_expr);
331 *flp = g_list_append(*flp, filt);
334 *pref_path_return = ff_path;
335 *errno_return = errno;
344 * Get a pointer to a list of filters.
347 get_filter_list(filter_list_type_t list)
354 flp = &capture_filters;
358 flp = &display_filters;
362 g_assert_not_reached();
369 * Get a pointer to the first entry in a filter list.
372 get_filter_list_first(filter_list_type_t list)
376 flp = get_filter_list(list);
377 return g_list_first(*flp);
381 * Add a new filter to the end of a list.
382 * Returns a pointer to the newly-added entry.
385 add_to_filter_list(filter_list_type_t list, const char *name,
386 const char *expression)
391 flp = get_filter_list(list);
392 filt = (filter_def *) g_malloc(sizeof(filter_def));
393 filt->name = g_strdup(name);
394 filt->strval = g_strdup(expression);
395 *flp = g_list_append(*flp, filt);
396 return g_list_last(*flp);
400 * Remove a filter from a list.
403 remove_from_filter_list(filter_list_type_t list, GList *fl_entry)
408 flp = get_filter_list(list);
409 filt = (filter_def *) fl_entry->data;
411 g_free(filt->strval);
413 *flp = g_list_remove_link(*flp, fl_entry);
417 * Write out a list of filters.
419 * On success, "*pref_path_return" is set to NULL.
420 * On error, "*pref_path_return" is set to point to the pathname of
421 * the file we tried to read - it should be freed by our caller -
422 * and "*errno_return" is set to the error.
425 save_filter_list(filter_list_type_t list, char **pref_path_return,
428 gchar *ff_path, *ff_path_new, *ff_name;
435 *pref_path_return = NULL; /* assume no error */
440 ff_name = CFILTER_FILE_NAME;
441 fl = capture_filters;
445 ff_name = DFILTER_FILE_NAME;
446 fl = display_filters;
450 g_assert_not_reached();
454 ff_path = get_persconffile_path(ff_name, TRUE);
456 /* Write to "XXX.new", and rename if that succeeds.
457 That means we don't trash the file if we fail to write it out
459 ff_path_new = (gchar *) g_malloc(strlen(ff_path) + 5);
460 sprintf(ff_path_new, "%s.new", ff_path);
462 if ((ff = fopen(ff_path_new, "w")) == NULL) {
463 *pref_path_return = ff_path;
464 *errno_return = errno;
468 flp = g_list_first(fl);
470 filt = (filter_def *) flp->data;
472 /* Write out the filter name as a quoted string; escape any quotes
475 for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) {
476 if (c == '"' || c == '\\')
482 /* Separate the filter name and value with a space. */
485 /* Write out the filter expression and a newline. */
486 fprintf(ff, "%s\n", filt->strval);
488 *pref_path_return = ff_path;
489 *errno_return = errno;
497 if (fclose(ff) == EOF) {
498 *pref_path_return = ff_path;
499 *errno_return = errno;
506 /* ANSI C doesn't say whether "rename()" removes the target if it
507 exists; the Win32 call to rename files doesn't do so, which I
508 infer is the reason why the MSVC++ "rename()" doesn't do so.
509 We must therefore remove the target file first, on Windows. */
510 if (remove(ff_path) < 0 && errno != ENOENT) {
511 /* It failed for some reason other than "it's not there"; if
512 it's not there, we don't need to remove it, so we just
514 *pref_path_return = ff_path;
515 *errno_return = errno;
522 if (rename(ff_path_new, ff_path) < 0) {
523 *pref_path_return = ff_path;
524 *errno_return = errno;