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>
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.
63 static GList *capture_filters = NULL;
66 * List of display filters.
68 static GList *display_filters = NULL;
71 * Read in a list of filters.
73 * On success, "*pref_path_return" is set to NULL.
74 * On error, "*pref_path_return" is set to point to the pathname of
75 * the file we tried to read - it should be freed by our caller -
76 * and "*errno_return" is set to the error.
79 #define INIT_BUF_SIZE 128
82 read_filter_list(filter_list_type_t list, char **pref_path_return,
92 char *filt_name, *filt_expr;
93 int filt_name_len, filt_expr_len;
94 int filt_name_index, filt_expr_index;
97 *pref_path_return = NULL; /* assume no error */
102 ff_name = CFILTER_FILE_NAME;
103 flp = &capture_filters;
107 ff_name = DFILTER_FILE_NAME;
108 flp = &display_filters;
112 g_assert_not_reached();
116 /* try to open personal "cfilters"/"dfilters" file */
117 ff_path = get_persconffile_path(ff_name, FALSE);
118 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
120 * Did that fail because the file didn't exist?
122 if (errno != ENOENT) {
126 *pref_path_return = ff_path;
127 *errno_return = errno;
132 * Yes. See if there's an "old style" personal "filters" file; if so, read it.
133 * This means that a user will start out with their capture and
134 * display filter lists being identical; each list may contain
135 * filters that don't belong in that list. The user can edit
136 * the filter lists, and delete the ones that don't belong in
140 ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE);
141 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
143 * Did that fail because the file didn't exist?
145 if (errno != ENOENT) {
149 *pref_path_return = ff_path;
150 *errno_return = errno;
155 * Try to open the global "cfilters/dfilters" file */
156 ff_path = get_datafile_path(ff_name);
157 if ((ff = eth_fopen(ff_path, "r")) == NULL) {
160 * Well, that didn't work, either. Just give up.
161 * Return an error if the file existed but we couldn't open it.
163 if (errno != ENOENT) {
164 *pref_path_return = ff_path;
165 *errno_return = errno;
172 /* If we already have a list of filters, discard it. */
174 fl_ent = g_list_first(*flp);
175 while (fl_ent != NULL) {
176 filt = (filter_def *) fl_ent->data;
178 g_free(filt->strval);
180 fl_ent = fl_ent->next;
186 /* Allocate the filter name buffer. */
187 filt_name_len = INIT_BUF_SIZE;
188 filt_name = g_malloc(filt_name_len + 1);
189 filt_expr_len = INIT_BUF_SIZE;
190 filt_expr = g_malloc(filt_expr_len + 1);
192 for (line = 1; ; line++) {
193 /* Lines in a filter file are of the form
197 where "name" is a name, in quotes - backslashes in the name
198 escape the next character, so quotes and backslashes can appear
199 in the name - and "expression" is a filter expression, not in
200 quotes, running to the end of the line. */
202 /* Skip over leading white space, if any. */
203 while ((c = getc(ff)) != EOF && isspace(c)) {
211 break; /* Nothing more to read */
213 /* "c" is the first non-white-space character.
214 If it's not a quote, it's an error. */
216 g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path,
219 c = getc(ff); /* skip to the end of the line */
223 /* Get the name of the filter. */
227 if (c == EOF || c == '\n')
228 break; /* End of line - or end of file */
231 if (filt_name_index >= filt_name_len) {
232 /* Filter name buffer isn't long enough; double its length. */
234 filt_name = g_realloc(filt_name, filt_name_len + 1);
236 filt_name[filt_name_index] = '\0';
240 /* Next character is escaped */
242 if (c == EOF || c == '\n')
243 break; /* End of line - or end of file */
245 /* Add this character to the filter name string. */
246 if (filt_name_index >= filt_name_len) {
247 /* Filter name buffer isn't long enough; double its length. */
249 filt_name = g_realloc(filt_name, filt_name_len + 1);
251 filt_name[filt_name_index] = c;
257 /* EOF, not error; no newline seen before EOF */
258 g_warning("'%s' line %d doesn't have a newline.", ff_path,
261 break; /* nothing more to read */
265 /* No newline seen before end-of-line */
266 g_warning("'%s' line %d doesn't have a closing quote.", ff_path,
271 /* Skip over separating white space, if any. */
272 while ((c = getc(ff)) != EOF && isspace(c)) {
279 /* EOF, not error; no newline seen before EOF */
280 g_warning("'%s' line %d doesn't have a newline.", ff_path,
283 break; /* nothing more to read */
287 /* No filter expression */
288 g_warning("'%s' line %d doesn't have a filter expression.", ff_path,
293 /* "c" is the first non-white-space character; it's the first
294 character of the filter expression. */
297 /* Add this character to the filter expression string. */
298 if (filt_expr_index >= filt_expr_len) {
299 /* Filter expressioin buffer isn't long enough; double its length. */
301 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
303 filt_expr[filt_expr_index] = c;
306 /* Get the next character. */
308 if (c == EOF || c == '\n')
314 /* EOF, not error; no newline seen before EOF */
315 g_warning("'%s' line %d doesn't have a newline.", ff_path,
318 break; /* nothing more to read */
321 /* We saw the ending newline; terminate the filter expression string */
322 if (filt_expr_index >= filt_expr_len) {
323 /* Filter expressioin buffer isn't long enough; double its length. */
325 filt_expr = g_realloc(filt_expr, filt_expr_len + 1);
327 filt_expr[filt_expr_index] = '\0';
329 /* Add the new filter to the list of filters */
330 filt = (filter_def *) g_malloc(sizeof(filter_def));
331 filt->name = g_strdup(filt_name);
332 filt->strval = g_strdup(filt_expr);
333 *flp = g_list_append(*flp, filt);
336 *pref_path_return = ff_path;
337 *errno_return = errno;
346 * Get a pointer to a list of filters.
349 get_filter_list(filter_list_type_t list)
356 flp = &capture_filters;
360 flp = &display_filters;
364 g_assert_not_reached();
371 * Get a pointer to the first entry in a filter list.
374 get_filter_list_first(filter_list_type_t list)
378 flp = get_filter_list(list);
379 return g_list_first(*flp);
383 * Add a new filter to the end of a list.
384 * Returns a pointer to the newly-added entry.
387 add_to_filter_list(filter_list_type_t list, const char *name,
388 const char *expression)
393 flp = get_filter_list(list);
394 filt = (filter_def *) g_malloc(sizeof(filter_def));
395 filt->name = g_strdup(name);
396 filt->strval = g_strdup(expression);
397 *flp = g_list_append(*flp, filt);
398 return g_list_last(*flp);
402 * Remove a filter from a list.
405 remove_from_filter_list(filter_list_type_t list, GList *fl_entry)
410 flp = get_filter_list(list);
411 filt = (filter_def *) fl_entry->data;
413 g_free(filt->strval);
415 *flp = g_list_remove_link(*flp, fl_entry);
419 * Write out a list of filters.
421 * On success, "*pref_path_return" is set to NULL.
422 * On error, "*pref_path_return" is set to point to the pathname of
423 * the file we tried to read - it should be freed by our caller -
424 * and "*errno_return" is set to the error.
427 save_filter_list(filter_list_type_t list, char **pref_path_return,
430 const gchar *ff_name;
431 gchar *ff_path, *ff_path_new;
438 *pref_path_return = NULL; /* assume no error */
443 ff_name = CFILTER_FILE_NAME;
444 fl = capture_filters;
448 ff_name = DFILTER_FILE_NAME;
449 fl = display_filters;
453 g_assert_not_reached();
457 ff_path = get_persconffile_path(ff_name, TRUE);
459 /* Write to "XXX.new", and rename if that succeeds.
460 That means we don't trash the file if we fail to write it out
462 ff_path_new = g_strdup_printf("%s.new", ff_path);
464 if ((ff = eth_fopen(ff_path_new, "w")) == NULL) {
465 *pref_path_return = ff_path;
466 *errno_return = errno;
470 flp = g_list_first(fl);
472 filt = (filter_def *) flp->data;
474 /* Write out the filter name as a quoted string; escape any quotes
477 for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) {
478 if (c == '"' || c == '\\')
484 /* Separate the filter name and value with a space. */
487 /* Write out the filter expression and a newline. */
488 fprintf(ff, "%s\n", filt->strval);
490 *pref_path_return = ff_path;
491 *errno_return = errno;
493 eth_unlink(ff_path_new);
499 if (fclose(ff) == EOF) {
500 *pref_path_return = ff_path;
501 *errno_return = errno;
502 eth_unlink(ff_path_new);
508 /* ANSI C doesn't say whether "rename()" removes the target if it
509 exists; the Win32 call to rename files doesn't do so, which I
510 infer is the reason why the MSVC++ "rename()" doesn't do so.
511 We must therefore remove the target file first, on Windows. */
512 if (eth_remove(ff_path) < 0 && errno != ENOENT) {
513 /* It failed for some reason other than "it's not there"; if
514 it's not there, we don't need to remove it, so we just
516 *pref_path_return = ff_path;
517 *errno_return = errno;
518 eth_unlink(ff_path_new);
524 if (eth_rename(ff_path_new, ff_path) < 0) {
525 *pref_path_return = ff_path;
526 *errno_return = errno;
527 eth_unlink(ff_path_new);