2 * Code for reading and writing the filters file.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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>
43 #include "file_util.h"
46 * Old filter file name.
48 #define FILTER_FILE_NAME "filters"
51 * Capture filter file name.
53 #define CFILTER_FILE_NAME "cfilters"
56 * Display filter file name.
58 #define DFILTER_FILE_NAME "dfilters"
61 * List of capture filters - saved.
63 static GList *capture_filters = NULL;
66 * List of display filters - saved.
68 static GList *display_filters = NULL;
71 * List of capture filters - currently edited.
73 static GList *capture_edited_filters = NULL;
76 * List of display filters - currently edited.
78 static GList *display_edited_filters = NULL;
81 * Read in a list of filters.
83 * On success, "*pref_path_return" is set to NULL.
84 * On error, "*pref_path_return" is set to point to the pathname of
85 * the file we tried to read - it should be freed by our caller -
86 * and "*errno_return" is set to the error.
89 #define INIT_BUF_SIZE 128
92 add_filter_entry(GList *fl, const char *filt_name, const char *filt_expr)
96 filt = (filter_def *) g_malloc(sizeof(filter_def));
97 filt->name = g_strdup(filt_name);
98 filt->strval = g_strdup(filt_expr);
99 return g_list_append(fl, filt);
103 remove_filter_entry(GList *fl, GList *fl_entry)
107 filt = (filter_def *) fl_entry->data;
109 g_free(filt->strval);
111 return g_list_remove_link(fl, fl_entry);
115 read_filter_list(filter_list_type_t list_type, char **pref_path_return,
123 char *filt_name, *filt_expr;
124 int filt_name_len, filt_expr_len;
125 int filt_name_index, filt_expr_index;
128 *pref_path_return = NULL; /* assume no error */
133 ff_name = CFILTER_FILE_NAME;
134 flpp = &capture_filters;
138 ff_name = DFILTER_FILE_NAME;
139 flpp = &display_filters;
143 g_assert_not_reached();
147 /* try to open personal "cfilters"/"dfilters" file */
148 ff_path = get_persconffile_path(ff_name, FALSE);
149 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
151 * Did that fail because the file didn't exist?
153 if (errno != ENOENT) {
157 *pref_path_return = ff_path;
158 *errno_return = errno;
163 * Yes. See if there's an "old style" personal "filters" file; if so, read it.
164 * This means that a user will start out with their capture and
165 * display filter lists being identical; each list may contain
166 * filters that don't belong in that list. The user can edit
167 * the filter lists, and delete the ones that don't belong in
171 ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE);
172 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
174 * Did that fail because the file didn't exist?
176 if (errno != ENOENT) {
180 *pref_path_return = ff_path;
181 *errno_return = errno;
186 * Try to open the global "cfilters/dfilters" file */
187 ff_path = get_datafile_path(ff_name);
188 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
191 * Well, that didn't work, either. Just give up.
192 * Return an error if the file existed but we couldn't open it.
194 if (errno != ENOENT) {
195 *pref_path_return = ff_path;
196 *errno_return = errno;
203 /* If we already have a list of filters, discard it. */
204 /* this should never happen - this function is called only once for each list! */
206 *flpp = remove_filter_entry(*flpp, g_list_first(*flpp));
209 /* Allocate the filter name buffer. */
210 filt_name_len = INIT_BUF_SIZE;
211 filt_name = g_malloc(filt_name_len + 1);
212 filt_expr_len = INIT_BUF_SIZE;
213 filt_expr = g_malloc(filt_expr_len + 1);
215 for (line = 1; ; line++) {
216 /* Lines in a filter file are of the form
220 where "name" is a name, in quotes - backslashes in the name
221 escape the next character, so quotes and backslashes can appear
222 in the name - and "expression" is a filter expression, not in
223 quotes, running to the end of the line. */
225 /* Skip over leading white space, if any. */
226 while ((c = getc(ff)) != EOF && isspace(c)) {
234 break; /* Nothing more to read */
236 /* "c" is the first non-white-space character.
237 If it's not a quote, it's an error. */
239 g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path,
242 c = getc(ff); /* skip to the end of the line */
246 /* Get the name of the filter. */
250 if (c == EOF || c == '\n')
251 break; /* End of line - or end of file */
254 if (filt_name_index >= filt_name_len) {
255 /* Filter name buffer isn't long enough; double its length. */
257 filt_name = g_realloc(filt_name, filt_name_len + 1);
259 filt_name[filt_name_index] = '\0';
263 /* Next character is escaped */
265 if (c == EOF || c == '\n')
266 break; /* End of line - or end of file */
268 /* Add this character to the filter name string. */
269 if (filt_name_index >= filt_name_len) {
270 /* Filter name buffer isn't long enough; double its length. */
272 filt_name = g_realloc(filt_name, filt_name_len + 1);
274 filt_name[filt_name_index] = c;
280 /* EOF, not error; no newline seen before EOF */
281 g_warning("'%s' line %d doesn't have a newline.", ff_path,
284 break; /* nothing more to read */
288 /* No newline seen before end-of-line */
289 g_warning("'%s' line %d doesn't have a closing quote.", ff_path,
294 /* Skip over separating white space, if any. */
295 while ((c = getc(ff)) != EOF && isspace(c)) {
302 /* EOF, not error; no newline seen before EOF */
303 g_warning("'%s' line %d doesn't have a newline.", ff_path,
306 break; /* nothing more to read */
310 /* No filter expression */
311 g_warning("'%s' line %d doesn't have a filter expression.", ff_path,
316 /* "c" is the first non-white-space character; it's the first
317 character of the filter expression. */
320 /* Add this character to the filter expression string. */
321 if (filt_expr_index >= filt_expr_len) {
322 /* Filter expressioin buffer isn't long enough; double its length. */
324 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
326 filt_expr[filt_expr_index] = c;
329 /* Get the next character. */
331 if (c == EOF || c == '\n')
337 /* EOF, not error; no newline seen before EOF */
338 g_warning("'%s' line %d doesn't have a newline.", ff_path,
341 break; /* nothing more to read */
344 /* We saw the ending newline; terminate the filter expression string */
345 if (filt_expr_index >= filt_expr_len) {
346 /* Filter expressioin buffer isn't long enough; double its length. */
348 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
350 filt_expr[filt_expr_index] = '\0';
352 /* Add the new filter to the list of filters */
353 *flpp = add_filter_entry(*flpp, filt_name, filt_expr);
356 *pref_path_return = ff_path;
357 *errno_return = errno;
364 /* init the corresponding edited list */
367 copy_filter_list(CFILTER_EDITED_LIST, CFILTER_LIST);
370 copy_filter_list(DFILTER_EDITED_LIST, DFILTER_LIST);
373 g_assert_not_reached();
379 * Get a pointer to a list of filters.
382 get_filter_list(filter_list_type_t list_type)
389 flpp = &capture_filters;
393 flpp = &display_filters;
396 case CFILTER_EDITED_LIST:
397 flpp = &capture_edited_filters;
400 case DFILTER_EDITED_LIST:
401 flpp = &display_edited_filters;
405 g_assert_not_reached();
412 * Get a pointer to the first entry in a filter list.
415 get_filter_list_first(filter_list_type_t list_type)
419 flpp = get_filter_list(list_type);
420 return g_list_first(*flpp);
424 * Add a new filter to the end of a list.
425 * Returns a pointer to the newly-added entry.
428 add_to_filter_list(filter_list_type_t list_type, const char *name,
429 const char *expression)
433 flpp = get_filter_list(list_type);
434 *flpp = add_filter_entry(*flpp, name, expression);
436 return g_list_last(*flpp);
440 * Remove a filter from a list.
443 remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry)
447 flpp = get_filter_list(list_type);
448 *flpp = remove_filter_entry(*flpp, fl_entry);
452 * Write out a list of filters.
454 * On success, "*pref_path_return" is set to NULL.
455 * On error, "*pref_path_return" is set to point to the pathname of
456 * the file we tried to read - it should be freed by our caller -
457 * and "*errno_return" is set to the error.
460 save_filter_list(filter_list_type_t list_type, char **pref_path_return,
463 const gchar *ff_name;
464 gchar *ff_path, *ff_path_new;
471 *pref_path_return = NULL; /* assume no error */
476 ff_name = CFILTER_FILE_NAME;
477 fl = capture_filters;
481 ff_name = DFILTER_FILE_NAME;
482 fl = display_filters;
486 g_assert_not_reached();
490 ff_path = get_persconffile_path(ff_name, TRUE);
492 /* Write to "XXX.new", and rename if that succeeds.
493 That means we don't trash the file if we fail to write it out
495 ff_path_new = g_strdup_printf("%s.new", ff_path);
497 if ((ff = eth_fopen(ff_path_new, "w")) == NULL) {
498 *pref_path_return = ff_path;
499 *errno_return = errno;
503 flpp = g_list_first(fl);
505 filt = (filter_def *) flpp->data;
507 /* Write out the filter name as a quoted string; escape any quotes
510 for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) {
511 if (c == '"' || c == '\\')
517 /* Separate the filter name and value with a space. */
520 /* Write out the filter expression and a newline. */
521 fprintf(ff, "%s\n", filt->strval);
523 *pref_path_return = ff_path;
524 *errno_return = errno;
526 eth_unlink(ff_path_new);
532 if (fclose(ff) == EOF) {
533 *pref_path_return = ff_path;
534 *errno_return = errno;
535 eth_unlink(ff_path_new);
541 /* ANSI C doesn't say whether "rename()" removes the target if it
542 exists; the Win32 call to rename files doesn't do so, which I
543 infer is the reason why the MSVC++ "rename()" doesn't do so.
544 We must therefore remove the target file first, on Windows. */
545 if (eth_remove(ff_path) < 0 && errno != ENOENT) {
546 /* It failed for some reason other than "it's not there"; if
547 it's not there, we don't need to remove it, so we just
549 *pref_path_return = ff_path;
550 *errno_return = errno;
551 eth_unlink(ff_path_new);
557 if (eth_rename(ff_path_new, ff_path) < 0) {
558 *pref_path_return = ff_path;
559 *errno_return = errno;
560 eth_unlink(ff_path_new);
569 * Copy a filter list into another.
571 void copy_filter_list(filter_list_type_t dest_type, filter_list_type_t src_type)
578 g_assert(dest_type != src_type);
580 flpp_dest = get_filter_list(dest_type);
581 flpp_src = get_filter_list(src_type);
584 /* throw away the "old" destination list - a NULL list is ok here */
586 *flpp_dest = remove_filter_entry(*flpp_dest, g_list_first(*flpp_dest));
588 g_assert(g_list_length(*flpp_dest) == 0);
590 /* copy the list entries */
592 filt = (flp_src)->data;
594 *flpp_dest = add_filter_entry(*flpp_dest, filt->name, filt->strval);
595 flp_src = g_list_next(flp_src);