Add support for a global "ethereal.conf" preferences file, stored in the
same directory as the "manuf" file ("/etc" or "/usr/local/etc", most likely). Add a mechanism to allow modules (e.g., dissectors) to register preference values, which: can be put into the global or the user's preference file; can be set from the command line, with arguments to the "-o" flag; can be set from tabs in the "Preferences" dialog box. Use that mechanism to register the "Decode IPv4 TOS field as DiffServ field" variable for IP as a preference. Stuff that still needs to be done: documenting the API for registering preferences; documenting the "-o" values in the man page (probably needs a flag similar to "-G", and a Perl script to turn the output into documentation as is done with the list of field); handling error checking for numeric values (range checking, making sure that if the user changes the variable from the GUI they change it to a valid numeric value); using the callbacks to, for example, update the display when preferences are changed (could be expensive); panic if the user specifies a numeric value with a base other than 10, 8, or 16. We may also want to clean up the existing wired-in preferences not to take effect the instant you tweak the widget, and to add an "Apply" button to the "Preferences" dialog. svn path=/trunk/; revision=2117
This commit is contained in:
parent
ed5651a909
commit
b1f950b377
|
@ -1,7 +1,7 @@
|
||||||
# Makefile.am
|
# Makefile.am
|
||||||
# Automake file for Ethereal
|
# Automake file for Ethereal
|
||||||
#
|
#
|
||||||
# $Id: Makefile.am,v 1.206 2000/06/22 06:37:59 guy Exp $
|
# $Id: Makefile.am,v 1.207 2000/07/05 09:40:37 guy Exp $
|
||||||
#
|
#
|
||||||
# Ethereal - Network traffic analyzer
|
# Ethereal - Network traffic analyzer
|
||||||
# By Gerald Combs <gerald@zing.org>
|
# By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -274,6 +274,7 @@ ETHEREAL_COMMON_SOURCES = \
|
||||||
ppptypes.h \
|
ppptypes.h \
|
||||||
prefs.c \
|
prefs.c \
|
||||||
prefs.h \
|
prefs.h \
|
||||||
|
prefs-int.h \
|
||||||
print.c \
|
print.c \
|
||||||
print.h \
|
print.h \
|
||||||
proto.c \
|
proto.c \
|
||||||
|
|
78
gtk/main.c
78
gtk/main.c
|
@ -1,6 +1,6 @@
|
||||||
/* main.c
|
/* main.c
|
||||||
*
|
*
|
||||||
* $Id: main.c,v 1.127 2000/07/05 02:04:16 guy Exp $
|
* $Id: main.c,v 1.128 2000/07/05 09:41:04 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -1144,15 +1144,16 @@ print_usage(void) {
|
||||||
fprintf(stderr, "%s [ -vh ] [ -kQS ] [ -b <bold font> ] [ -B <byte view height> ]\n",
|
fprintf(stderr, "%s [ -vh ] [ -kQS ] [ -b <bold font> ] [ -B <byte view height> ]\n",
|
||||||
PACKAGE);
|
PACKAGE);
|
||||||
fprintf(stderr, "\t[ -c count ] [ -D ] [ -f <capture filter> ] [ -i interface ]\n");
|
fprintf(stderr, "\t[ -c count ] [ -D ] [ -f <capture filter> ] [ -i interface ]\n");
|
||||||
fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -P <packet list height> ] [ -r infile ]\n");
|
fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -o <preference setting> ] ...\n");
|
||||||
fprintf(stderr, "\t[ -R <read filter> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
|
fprintf(stderr, "\t[ -P <packet list height> ] [ -r infile ] [ -R <read filter> ]\n");
|
||||||
fprintf(stderr, "\t[ -T <tree view height> ] [ -w savefile ]\n");
|
fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -T <tree view height> ]\n");
|
||||||
|
fprintf(stderr, "\t[ -w savefile ]\n");
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "%s [ -vh ] [ -b <bold font> ] [ -B <byte view height> ]\n",
|
fprintf(stderr, "%s [ -vh ] [ -b <bold font> ] [ -B <byte view height> ]\n",
|
||||||
PACKAGE);
|
PACKAGE);
|
||||||
fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -P <packet list height> ] [ -r infile ]\n");
|
fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -o <preference setting ] ...\n");
|
||||||
fprintf(stderr, "\t[ -R <read filter> ] [ -t <time stamp format> ]\n");
|
fprintf(stderr, "\t[ -P <packet list height> ] [ -r infile ] [ -R <read filter> ]\n");
|
||||||
fprintf(stderr, "\t[ -T <tree view height> ]\n");
|
fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1175,8 +1176,8 @@ main(int argc, char *argv[])
|
||||||
extern char pcap_version[];
|
extern char pcap_version[];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
char *pf_path;
|
char *gpf_path, *pf_path;
|
||||||
int pf_open_errno = 0;
|
int gpf_open_errno, pf_open_errno;
|
||||||
int err;
|
int err;
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
gboolean start_capture = FALSE;
|
gboolean start_capture = FALSE;
|
||||||
|
@ -1201,6 +1202,16 @@ main(int argc, char *argv[])
|
||||||
capture_child = (strcmp(command_name, CHILD_NAME) == 0);
|
capture_child = (strcmp(command_name, CHILD_NAME) == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Register all dissectors; we must do this before checking for the
|
||||||
|
"-G" flag, as the "-G" flag dumps a list of fields registered
|
||||||
|
by the dissectors, and we must do it before we read the preferences,
|
||||||
|
in case any dissectors register preferences. */
|
||||||
|
dissect_init();
|
||||||
|
|
||||||
|
/* Now register the preferences for any non-dissector modules.
|
||||||
|
We must do that before we read the preferences as well. */
|
||||||
|
prefs_register_modules();
|
||||||
|
|
||||||
/* If invoked with the "-G" flag, we dump out a glossary of
|
/* If invoked with the "-G" flag, we dump out a glossary of
|
||||||
display filter symbols.
|
display filter symbols.
|
||||||
|
|
||||||
|
@ -1221,7 +1232,6 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
any arguments after the "-G" flag will not be used. */
|
any arguments after the "-G" flag will not be used. */
|
||||||
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
|
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
|
||||||
dissect_init();
|
|
||||||
proto_registrar_dump();
|
proto_registrar_dump();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -1235,13 +1245,7 @@ main(int argc, char *argv[])
|
||||||
/* Let GTK get its args */
|
/* Let GTK get its args */
|
||||||
gtk_init (&argc, &argv);
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
prefs = read_prefs(&pf_path);
|
prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
|
||||||
if (pf_path != NULL) {
|
|
||||||
/* The preferences file exists, but couldn't be opened; "pf_path" is
|
|
||||||
its pathname. Remember "errno", as that says why the attempt
|
|
||||||
failed. */
|
|
||||||
pf_open_errno = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the capture file struct */
|
/* Initialize the capture file struct */
|
||||||
cfile.plist = NULL;
|
cfile.plist = NULL;
|
||||||
|
@ -1312,7 +1316,7 @@ main(int argc, char *argv[])
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Now get our args */
|
/* Now get our args */
|
||||||
while ((opt = getopt(argc, argv, "b:B:c:Df:hi:km:nP:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
|
while ((opt = getopt(argc, argv, "b:B:c:Df:hi:km:no:P:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'b': /* Bold font */
|
case 'b': /* Bold font */
|
||||||
bold_font = g_strdup(optarg);
|
bold_font = g_strdup(optarg);
|
||||||
|
@ -1367,6 +1371,21 @@ main(int argc, char *argv[])
|
||||||
case 'n': /* No name resolution */
|
case 'n': /* No name resolution */
|
||||||
g_resolving_actif = 0;
|
g_resolving_actif = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'o': /* Override preference from command line */
|
||||||
|
switch (prefs_set_pref(optarg)) {
|
||||||
|
|
||||||
|
case PREFS_SET_SYNTAX_ERR:
|
||||||
|
fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREFS_SET_NO_SUCH_PREF:
|
||||||
|
fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
|
||||||
|
optarg);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'P': /* Packet list pane height */
|
case 'P': /* Packet list pane height */
|
||||||
pl_size = atoi(optarg);
|
pl_size = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -1541,12 +1560,6 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
create_main_window(pl_size, tv_size, bv_size, prefs);
|
create_main_window(pl_size, tv_size, bv_size, prefs);
|
||||||
|
|
||||||
/*
|
|
||||||
Hmmm should we do it here
|
|
||||||
*/
|
|
||||||
|
|
||||||
dissect_init(); /* Init anything that needs initializing */
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
/* Is this a "child" ethereal, which is only supposed to pop up a
|
/* Is this a "child" ethereal, which is only supposed to pop up a
|
||||||
capture box to let us stop the capture, and run a capture
|
capture box to let us stop the capture, and run a capture
|
||||||
|
@ -1611,12 +1624,21 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we failed to open the preferences file, pop up an alert box;
|
/* If the global preferences file exists but we failed to open it,
|
||||||
we defer it until now, so that the alert box is more likely to
|
pop up an alert box; we defer that until now, so that the alert
|
||||||
come up on top of the main window. */
|
box is more likely to come up on top of the main window. */
|
||||||
|
if (gpf_path != NULL) {
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
"Could not open global preferences file\n\"%s\": %s.", gpf_path,
|
||||||
|
strerror(gpf_open_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the user's preferences file exists but we failed to open it,
|
||||||
|
pop up an alert box; we defer that until now, so that the alert
|
||||||
|
box is more likely to come up on top of the main window. */
|
||||||
if (pf_path != NULL) {
|
if (pf_path != NULL) {
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
"Could not open preferences file\n\"%s\": %s.", pf_path,
|
"Could not open your preferences file\n\"%s\": %s.", pf_path,
|
||||||
strerror(pf_open_errno));
|
strerror(pf_open_errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
297
gtk/prefs_dlg.c
297
gtk/prefs_dlg.c
|
@ -1,7 +1,7 @@
|
||||||
/* prefs_dlg.c
|
/* prefs_dlg.c
|
||||||
* Routines for handling preferences
|
* Routines for handling preferences
|
||||||
*
|
*
|
||||||
* $Id: prefs_dlg.c,v 1.13 2000/07/05 06:33:02 guy Exp $
|
* $Id: prefs_dlg.c,v 1.14 2000/07/05 09:41:07 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -59,6 +59,8 @@
|
||||||
#include "dlg_utils.h"
|
#include "dlg_utils.h"
|
||||||
#include "simple_dialog.h"
|
#include "simple_dialog.h"
|
||||||
|
|
||||||
|
#include "prefs-int.h"
|
||||||
|
|
||||||
static void prefs_main_ok_cb(GtkWidget *, gpointer);
|
static void prefs_main_ok_cb(GtkWidget *, gpointer);
|
||||||
static void prefs_main_save_cb(GtkWidget *, gpointer);
|
static void prefs_main_save_cb(GtkWidget *, gpointer);
|
||||||
static void prefs_main_cancel_cb(GtkWidget *, gpointer);
|
static void prefs_main_cancel_cb(GtkWidget *, gpointer);
|
||||||
|
@ -78,6 +80,154 @@ static void prefs_main_destroy_cb(GtkWidget *, gpointer);
|
||||||
*/
|
*/
|
||||||
static GtkWidget *prefs_w;
|
static GtkWidget *prefs_w;
|
||||||
|
|
||||||
|
static void
|
||||||
|
pref_show(pref_t *pref, gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkWidget *main_tb = user_data;
|
||||||
|
const char *title;
|
||||||
|
char *label_string;
|
||||||
|
GtkWidget *label, *menu, *menu_item, *widget, *button;
|
||||||
|
GSList *rb_group;
|
||||||
|
char uint_str[10+1];
|
||||||
|
const enum_val *enum_valp;
|
||||||
|
int menu_index, index;
|
||||||
|
|
||||||
|
/* Give this preference a label which is its title, followed by a colon,
|
||||||
|
and left-align it. */
|
||||||
|
title = pref->title;
|
||||||
|
label_string = g_malloc(strlen(title) + 2);
|
||||||
|
strcpy(label_string, title);
|
||||||
|
strcat(label_string, ":");
|
||||||
|
label = gtk_label_new(label_string);
|
||||||
|
g_free(label_string);
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
|
||||||
|
|
||||||
|
/* Attach it to the table. */
|
||||||
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, pref->ordinal,
|
||||||
|
pref->ordinal+1);
|
||||||
|
|
||||||
|
/* Save the current value of the preference, so that we can revert it if
|
||||||
|
the user does "Apply" and then "Cancel", and create the control for
|
||||||
|
editing the preference. */
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
pref->saved_val.uint = *pref->varp.uint;
|
||||||
|
|
||||||
|
/* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
|
||||||
|
Even more annoyingly, even if there were, GLib doesn't define
|
||||||
|
G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
|
||||||
|
use that. */
|
||||||
|
widget = gtk_entry_new();
|
||||||
|
switch (pref->info.base) {
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
sprintf(uint_str, "%u", pref->saved_val.uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
sprintf(uint_str, "%o", pref->saved_val.uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
sprintf(uint_str, "%x", pref->saved_val.uint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(widget), uint_str);
|
||||||
|
pref->control = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
pref->saved_val.bool = *pref->varp.bool;
|
||||||
|
widget = gtk_check_button_new();
|
||||||
|
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), pref->saved_val.bool);
|
||||||
|
pref->control = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
pref->saved_val.enumval = *pref->varp.enump;
|
||||||
|
if (pref->info.enum_info.radio_buttons) {
|
||||||
|
/* Show it as radio buttons. */
|
||||||
|
widget = gtk_hbox_new(FALSE, 0);
|
||||||
|
rb_group = NULL;
|
||||||
|
for (enum_valp = pref->info.enum_info.enumvals, index = 0;
|
||||||
|
enum_valp->name != NULL; enum_valp++, index++) {
|
||||||
|
button = gtk_radio_button_new_with_label(rb_group, enum_valp->name);
|
||||||
|
if (rb_group == NULL)
|
||||||
|
rb_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
|
||||||
|
gtk_box_pack_start(GTK_BOX(widget), button, FALSE, FALSE, 10);
|
||||||
|
if (enum_valp->value == pref->saved_val.enumval)
|
||||||
|
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
|
||||||
|
pref->control = button;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Show it as an option menu. */
|
||||||
|
menu = gtk_menu_new();
|
||||||
|
menu_index = -1;
|
||||||
|
for (enum_valp = pref->info.enum_info.enumvals, index = 0;
|
||||||
|
enum_valp->name != NULL; enum_valp++, index++) {
|
||||||
|
menu_item = gtk_menu_item_new_with_label(enum_valp->name);
|
||||||
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
||||||
|
if (enum_valp->value == pref->saved_val.enumval)
|
||||||
|
menu_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the option menu from the option */
|
||||||
|
widget = gtk_option_menu_new();
|
||||||
|
gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu);
|
||||||
|
|
||||||
|
/* Set its current value to the variable's current value */
|
||||||
|
if (menu_index != -1)
|
||||||
|
gtk_option_menu_set_history(GTK_OPTION_MENU(widget), menu_index);
|
||||||
|
pref->control = widget;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
widget = gtk_entry_new();
|
||||||
|
if (pref->saved_val.string != NULL)
|
||||||
|
g_free(pref->saved_val.string);
|
||||||
|
pref->saved_val.string = g_strdup(*pref->varp.string);
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(widget), pref->saved_val.string);
|
||||||
|
pref->control = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
widget = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), widget, 1, 2, pref->ordinal,
|
||||||
|
pref->ordinal+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_prefs_show(module_t *module, gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkWidget *prefs_nb = user_data;
|
||||||
|
GtkWidget *main_vb, *main_tb, *label;
|
||||||
|
|
||||||
|
/* Main vertical box */
|
||||||
|
main_vb = gtk_vbox_new(FALSE, 5);
|
||||||
|
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
||||||
|
|
||||||
|
/* Main table */
|
||||||
|
main_tb = gtk_table_new(module->numprefs, 2, FALSE);
|
||||||
|
gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
|
||||||
|
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
|
||||||
|
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
|
||||||
|
|
||||||
|
/* Add items for each of the preferences */
|
||||||
|
prefs_pref_foreach(module, pref_show, main_tb);
|
||||||
|
|
||||||
|
label = gtk_label_new(module->title);
|
||||||
|
gtk_notebook_append_page(GTK_NOTEBOOK(prefs_nb), main_vb, label);
|
||||||
|
|
||||||
|
/* Show 'em what we got */
|
||||||
|
gtk_widget_show_all(main_vb);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prefs_cb(GtkWidget *w, gpointer dummy) {
|
prefs_cb(GtkWidget *w, gpointer dummy) {
|
||||||
GtkWidget *main_vb, *top_hb, *bbox, *prefs_nb,
|
GtkWidget *main_vb, *top_hb, *bbox, *prefs_nb,
|
||||||
|
@ -136,6 +286,9 @@ prefs_cb(GtkWidget *w, gpointer dummy) {
|
||||||
label = gtk_label_new ("GUI");
|
label = gtk_label_new ("GUI");
|
||||||
gtk_notebook_append_page (GTK_NOTEBOOK(prefs_nb), gui_pg, label);
|
gtk_notebook_append_page (GTK_NOTEBOOK(prefs_nb), gui_pg, label);
|
||||||
|
|
||||||
|
/* Registered prefs */
|
||||||
|
prefs_module_foreach(module_prefs_show, prefs_nb);
|
||||||
|
|
||||||
/* Button row: OK and cancel buttons */
|
/* Button row: OK and cancel buttons */
|
||||||
bbox = gtk_hbutton_box_new();
|
bbox = gtk_hbutton_box_new();
|
||||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
|
||||||
|
@ -173,6 +326,109 @@ prefs_cb(GtkWidget *w, gpointer dummy) {
|
||||||
gtk_widget_show(prefs_w);
|
gtk_widget_show(prefs_w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pref_fetch(pref_t *pref, gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkWidget *label;
|
||||||
|
char *label_string;
|
||||||
|
char *str_val;
|
||||||
|
char *p;
|
||||||
|
guint uval;
|
||||||
|
GSList *rb_entry;
|
||||||
|
GtkWidget *button;
|
||||||
|
|
||||||
|
/* Fetch the value of the preference, and set the appropriate variable
|
||||||
|
to it. */
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
|
||||||
|
uval = strtoul(str_val, &p, pref->info.base);
|
||||||
|
#if 0
|
||||||
|
if (p == value || *p != '\0')
|
||||||
|
return PREFS_SET_SYNTAX_ERR; /* number was bad */
|
||||||
|
#endif
|
||||||
|
*pref->varp.uint = uval;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
*pref->varp.bool = GTK_TOGGLE_BUTTON(pref->control)->active;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
if (pref->info.enum_info.radio_buttons) {
|
||||||
|
/* Go through the list of of radio buttons in the group, and find
|
||||||
|
the first one that's active. */
|
||||||
|
button = NULL;
|
||||||
|
for (rb_entry = gtk_radio_button_group(GTK_RADIO_BUTTON(pref->control));
|
||||||
|
rb_entry != NULL;
|
||||||
|
rb_entry = g_slist_next(rb_entry)) {
|
||||||
|
button = rb_entry->data;
|
||||||
|
if (GTK_TOGGLE_BUTTON(button)->active)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* OK, now find that button's label. */
|
||||||
|
label = GTK_BIN(button)->child;
|
||||||
|
} else {
|
||||||
|
/* Get the label for the currently active entry in the option menu.
|
||||||
|
Yes, this is how you do it. See FAQ 6.8 in the GTK+ FAQ. */
|
||||||
|
label = GTK_BIN(pref->control)->child;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the label, and translate it to a value. */
|
||||||
|
gtk_label_get(GTK_LABEL(label), &label_string);
|
||||||
|
*pref->varp.enump = find_val_for_string(label_string,
|
||||||
|
pref->info.enum_info.enumvals, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
|
||||||
|
if (*pref->varp.string != NULL)
|
||||||
|
g_free(*pref->varp.string);
|
||||||
|
*pref->varp.string = g_strdup(str_val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_prefs_fetch(module_t *module, gpointer user_data)
|
||||||
|
{
|
||||||
|
/* For all preferences in this module, fetch its value from this
|
||||||
|
module's notebook page. */
|
||||||
|
prefs_pref_foreach(module, pref_fetch, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pref_clean(pref_t *pref, gpointer user_data)
|
||||||
|
{
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
if (pref->saved_val.string != NULL) {
|
||||||
|
g_free(pref->saved_val.string);
|
||||||
|
pref->saved_val.string = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_prefs_clean(module_t *module, gpointer user_data)
|
||||||
|
{
|
||||||
|
/* For all preferences in this module, clean up any cruft allocated for
|
||||||
|
use by the GUI code. */
|
||||||
|
prefs_pref_foreach(module, pref_clean, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prefs_main_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
|
prefs_main_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +436,8 @@ prefs_main_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
|
||||||
column_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
column_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
||||||
stream_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
stream_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
||||||
gui_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
gui_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
||||||
|
prefs_module_foreach(module_prefs_fetch, NULL);
|
||||||
|
prefs_module_foreach(module_prefs_clean, NULL);
|
||||||
gtk_widget_destroy(GTK_WIDGET(parent_w));
|
gtk_widget_destroy(GTK_WIDGET(parent_w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +451,7 @@ prefs_main_save_cb(GtkWidget *save_bt, gpointer parent_w)
|
||||||
column_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
column_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
||||||
stream_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
stream_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
||||||
gui_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
gui_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
||||||
|
prefs_module_foreach(module_prefs_fetch, NULL);
|
||||||
err = write_prefs(&pf_path);
|
err = write_prefs(&pf_path);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
@ -201,6 +460,41 @@ prefs_main_save_cb(GtkWidget *save_bt, gpointer parent_w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pref_revert(pref_t *pref, gpointer user_data)
|
||||||
|
{
|
||||||
|
/* Fetch the value of the preference, and set the appropriate variable
|
||||||
|
to it. */
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
*pref->varp.uint = pref->saved_val.uint;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
*pref->varp.bool = pref->saved_val.bool;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
*pref->varp.enump = pref->saved_val.enumval;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
if (*pref->varp.string != NULL)
|
||||||
|
g_free(*pref->varp.string);
|
||||||
|
*pref->varp.string = g_strdup(pref->saved_val.string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_prefs_revert(module_t *module, gpointer user_data)
|
||||||
|
{
|
||||||
|
/* For all preferences in this module, revert its value to the value
|
||||||
|
it had when we popped up the Preferences dialog. */
|
||||||
|
prefs_pref_foreach(module, pref_revert, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prefs_main_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w)
|
prefs_main_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +502,7 @@ prefs_main_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w)
|
||||||
column_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
column_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY));
|
||||||
stream_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
stream_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY));
|
||||||
gui_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
gui_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY));
|
||||||
|
prefs_module_foreach(module_prefs_revert, NULL);
|
||||||
gtk_widget_destroy(GTK_WIDGET(parent_w));
|
gtk_widget_destroy(GTK_WIDGET(parent_w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
packet-ip.c
11
packet-ip.c
|
@ -1,7 +1,7 @@
|
||||||
/* packet-ip.c
|
/* packet-ip.c
|
||||||
* Routines for IP and miscellaneous IP protocol packet disassembly
|
* Routines for IP and miscellaneous IP protocol packet disassembly
|
||||||
*
|
*
|
||||||
* $Id: packet-ip.c,v 1.94 2000/06/20 13:21:55 gram Exp $
|
* $Id: packet-ip.c,v 1.95 2000/07/05 09:40:38 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "resolv.h"
|
#include "resolv.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
|
||||||
#ifdef NEED_SNPRINTF_H
|
#ifdef NEED_SNPRINTF_H
|
||||||
# ifdef HAVE_STDARG_H
|
# ifdef HAVE_STDARG_H
|
||||||
|
@ -1390,6 +1391,7 @@ proto_register_ip(void)
|
||||||
&ett_ip_option_route,
|
&ett_ip_option_route,
|
||||||
&ett_ip_option_timestamp,
|
&ett_ip_option_timestamp,
|
||||||
};
|
};
|
||||||
|
module_t *ip_module;
|
||||||
|
|
||||||
proto_ip = proto_register_protocol ("Internet Protocol", "ip");
|
proto_ip = proto_register_protocol ("Internet Protocol", "ip");
|
||||||
proto_register_field_array(proto_ip, hf, array_length(hf));
|
proto_register_field_array(proto_ip, hf, array_length(hf));
|
||||||
|
@ -1397,6 +1399,13 @@ proto_register_ip(void)
|
||||||
|
|
||||||
/* subdissector code */
|
/* subdissector code */
|
||||||
ip_dissector_table = register_dissector_table("ip.proto");
|
ip_dissector_table = register_dissector_table("ip.proto");
|
||||||
|
|
||||||
|
/* Register a configuration option for decoding TOS as DSCP */
|
||||||
|
ip_module = prefs_register_module("ip", "IP", NULL);
|
||||||
|
prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
|
||||||
|
"Decode IPv4 TOS field as DiffServ field",
|
||||||
|
"Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
|
||||||
|
&g_ip_dscp_actif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* prefs-int.h
|
||||||
|
* Definitions for implementation of preference handling routines;
|
||||||
|
* used by "friends" of the preferences type.
|
||||||
|
*
|
||||||
|
* $Id: prefs-int.h,v 1.1 2000/07/05 09:40:40 guy Exp $
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PREFS_INT_H__
|
||||||
|
#define __PREFS_INT_H__
|
||||||
|
|
||||||
|
struct pref_module {
|
||||||
|
const char *name; /* name of module */
|
||||||
|
const char *title; /* title of module (displayed in preferences notebook) */
|
||||||
|
void (*apply_cb)(void); /* routine to call when preferences applied */
|
||||||
|
GList *prefs; /* list of its preferences */
|
||||||
|
int numprefs; /* number of preferences */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PREF_UINT,
|
||||||
|
PREF_BOOL,
|
||||||
|
PREF_ENUM,
|
||||||
|
PREF_STRING
|
||||||
|
} pref_type_t;
|
||||||
|
|
||||||
|
struct preference {
|
||||||
|
const char *name; /* name of preference */
|
||||||
|
const char *title; /* title to use in GUI */
|
||||||
|
const char *description; /* human-readable description of preference */
|
||||||
|
int ordinal; /* ordinal number of this preference */
|
||||||
|
pref_type_t type; /* type of that preference */
|
||||||
|
union {
|
||||||
|
guint *uint;
|
||||||
|
gboolean *bool;
|
||||||
|
gint *enump;
|
||||||
|
char **string;
|
||||||
|
} varp; /* pointer to variable storing the value */
|
||||||
|
union {
|
||||||
|
guint uint;
|
||||||
|
gboolean bool;
|
||||||
|
gint enumval;
|
||||||
|
char *string;
|
||||||
|
} saved_val; /* original value, when editing from the GUI */
|
||||||
|
union {
|
||||||
|
guint base; /* input/output base, for PREF_UINT */
|
||||||
|
struct {
|
||||||
|
const enum_val *enumvals; /* list of name & values */
|
||||||
|
gboolean radio_buttons; /* TRUE if it should be shown as
|
||||||
|
radio buttons rather than as an
|
||||||
|
option menu or combo box in
|
||||||
|
the preferences tab */
|
||||||
|
} enum_info; /* for PREF_ENUM */
|
||||||
|
} info; /* display/text file information */
|
||||||
|
void *control; /* handle for GUI control for this preference */
|
||||||
|
};
|
||||||
|
|
||||||
|
gint find_val_for_string(const char *needle, const enum_val *haystack,
|
||||||
|
gint default_value);
|
||||||
|
|
||||||
|
#endif /* prefs-int.h */
|
579
prefs.c
579
prefs.c
|
@ -1,7 +1,7 @@
|
||||||
/* prefs.c
|
/* prefs.c
|
||||||
* Routines for handling preferences
|
* Routines for handling preferences
|
||||||
*
|
*
|
||||||
* $Id: prefs.c,v 1.30 2000/01/29 16:41:14 gram Exp $
|
* $Id: prefs.c,v 1.31 2000/07/05 09:40:41 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
@ -53,6 +54,8 @@
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "prefs-int.h"
|
||||||
|
|
||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
static int set_pref(gchar*, gchar*);
|
static int set_pref(gchar*, gchar*);
|
||||||
static GList *get_string_list(gchar *);
|
static GList *get_string_list(gchar *);
|
||||||
|
@ -60,7 +63,9 @@ static void clear_string_list(GList *);
|
||||||
|
|
||||||
#define PF_NAME "preferences"
|
#define PF_NAME "preferences"
|
||||||
|
|
||||||
static int init_prefs = 1;
|
#define GPF_PATH DATAFILE_DIR "/ethereal.conf"
|
||||||
|
|
||||||
|
static gboolean init_prefs = TRUE;
|
||||||
static gchar *pf_path = NULL;
|
static gchar *pf_path = NULL;
|
||||||
|
|
||||||
e_prefs prefs;
|
e_prefs prefs;
|
||||||
|
@ -72,6 +77,244 @@ gchar *gui_ptree_expander_style_text[] =
|
||||||
{ "NONE", "SQUARE", "TRIANGLE", "CIRCULAR", NULL };
|
{ "NONE", "SQUARE", "TRIANGLE", "CIRCULAR", NULL };
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of modules with preference settings.
|
||||||
|
*/
|
||||||
|
static GList *modules;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a module that will have preferences.
|
||||||
|
* Specify the name used for the module in the preferences file, the
|
||||||
|
* title used in the tab for it in a preferences dialog box, and a
|
||||||
|
* routine to call back when we apply the preferences.
|
||||||
|
*/
|
||||||
|
module_t *
|
||||||
|
prefs_register_module(const char *name, const char *title,
|
||||||
|
void (*apply_cb)(void))
|
||||||
|
{
|
||||||
|
module_t *module;
|
||||||
|
|
||||||
|
module = g_malloc(sizeof (module_t));
|
||||||
|
module->name = name;
|
||||||
|
module->title = title;
|
||||||
|
module->apply_cb = apply_cb;
|
||||||
|
module->prefs = NULL; /* no preferences, to start */
|
||||||
|
module->numprefs = 0;
|
||||||
|
|
||||||
|
modules = g_list_append(modules, module);
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a module, given its name.
|
||||||
|
*/
|
||||||
|
static gint
|
||||||
|
module_match(gconstpointer a, gconstpointer b)
|
||||||
|
{
|
||||||
|
const module_t *module = a;
|
||||||
|
const char *name = b;
|
||||||
|
|
||||||
|
return strcmp(name, module->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static module_t *
|
||||||
|
find_module(char *name)
|
||||||
|
{
|
||||||
|
GList *list_entry;
|
||||||
|
|
||||||
|
list_entry = g_list_find_custom(modules, name, module_match);
|
||||||
|
if (list_entry == NULL)
|
||||||
|
return NULL; /* no such module */
|
||||||
|
return (module_t *) list_entry->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
module_cb callback;
|
||||||
|
gpointer user_data;
|
||||||
|
} module_cb_arg_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_module_callback(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
module_t *module = data;
|
||||||
|
module_cb_arg_t *arg = user_data;
|
||||||
|
|
||||||
|
(*arg->callback)(module, arg->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each module.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_module_foreach(module_cb callback, gpointer user_data)
|
||||||
|
{
|
||||||
|
module_cb_arg_t arg;
|
||||||
|
|
||||||
|
arg.callback = callback;
|
||||||
|
arg.user_data = user_data;
|
||||||
|
g_list_foreach(modules, do_module_callback, &arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
call_apply_cb(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
module_t *module = data;
|
||||||
|
|
||||||
|
(*module->apply_cb)();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call the "apply" callback function for each module.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_apply_all(void)
|
||||||
|
{
|
||||||
|
g_list_foreach(modules, call_apply_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference in a module's list of preferences.
|
||||||
|
*/
|
||||||
|
static pref_t *
|
||||||
|
register_preference(module_t *module, const char *name, const char *title,
|
||||||
|
const char *description)
|
||||||
|
{
|
||||||
|
pref_t *preference;
|
||||||
|
|
||||||
|
preference = g_malloc(sizeof (pref_t));
|
||||||
|
preference->name = name;
|
||||||
|
preference->title = title;
|
||||||
|
preference->description = description;
|
||||||
|
preference->ordinal = module->numprefs;
|
||||||
|
|
||||||
|
module->prefs = g_list_append(module->prefs, preference);
|
||||||
|
module->numprefs++;
|
||||||
|
|
||||||
|
return preference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a preference in a module's list of preferences, given the module
|
||||||
|
* and the preference's name.
|
||||||
|
*/
|
||||||
|
static gint
|
||||||
|
preference_match(gconstpointer a, gconstpointer b)
|
||||||
|
{
|
||||||
|
const pref_t *pref = a;
|
||||||
|
const char *name = b;
|
||||||
|
|
||||||
|
return strcmp(name, pref->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct preference *
|
||||||
|
find_preference(module_t *module, char *name)
|
||||||
|
{
|
||||||
|
GList *list_entry;
|
||||||
|
|
||||||
|
list_entry = g_list_find_custom(module->prefs, name, preference_match);
|
||||||
|
if (list_entry == NULL)
|
||||||
|
return NULL; /* no such preference */
|
||||||
|
return (struct preference *) list_entry->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an unsigned integral value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_register_uint_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, guint base, guint *var)
|
||||||
|
{
|
||||||
|
pref_t *preference;
|
||||||
|
|
||||||
|
preference = register_preference(module, name, title, description);
|
||||||
|
preference->type = PREF_UINT;
|
||||||
|
preference->varp.uint = var;
|
||||||
|
preference->info.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an Boolean value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_register_bool_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, gboolean *var)
|
||||||
|
{
|
||||||
|
pref_t *preference;
|
||||||
|
|
||||||
|
preference = register_preference(module, name, title, description);
|
||||||
|
preference->type = PREF_BOOL;
|
||||||
|
preference->varp.bool = var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an enumerated value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_register_enum_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, gint *var,
|
||||||
|
const enum_val *enumvals, gboolean radio_buttons)
|
||||||
|
{
|
||||||
|
pref_t *preference;
|
||||||
|
|
||||||
|
preference = register_preference(module, name, title, description);
|
||||||
|
preference->type = PREF_ENUM;
|
||||||
|
preference->varp.enump = var;
|
||||||
|
preference->info.enum_info.enumvals = enumvals;
|
||||||
|
preference->info.enum_info.radio_buttons = radio_buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with a character-string value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_register_string_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, char **var)
|
||||||
|
{
|
||||||
|
pref_t *preference;
|
||||||
|
|
||||||
|
preference = register_preference(module, name, title, description);
|
||||||
|
preference->type = PREF_STRING;
|
||||||
|
preference->varp.string = var;
|
||||||
|
preference->saved_val.string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pref_cb callback;
|
||||||
|
gpointer user_data;
|
||||||
|
} pref_cb_arg_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_pref_callback(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
pref_t *pref = data;
|
||||||
|
pref_cb_arg_t *arg = user_data;
|
||||||
|
|
||||||
|
(*arg->callback)(pref, arg->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each preference
|
||||||
|
* in a given module.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
|
||||||
|
{
|
||||||
|
pref_cb_arg_t arg;
|
||||||
|
|
||||||
|
arg.callback = callback;
|
||||||
|
arg.user_data = user_data;
|
||||||
|
g_list_foreach(module->prefs, do_pref_callback, &arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register all non-dissector modules' preferences.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_register_modules(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse through a list of comma-separated, quoted strings. Return a
|
/* Parse through a list of comma-separated, quoted strings. Return a
|
||||||
list of the string data */
|
list of the string data */
|
||||||
static GList *
|
static GList *
|
||||||
|
@ -129,6 +372,29 @@ clear_string_list(GList *sl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Takes a string, a pointer to an array of "enum_val"s, and a default gint
|
||||||
|
* value.
|
||||||
|
* The array must be terminated by an entry with a null "name" string.
|
||||||
|
* If the string matches a "name" strings in an entry, the value from that
|
||||||
|
* entry is returned. Otherwise, the default value that was passed as the
|
||||||
|
* third argument is returned.
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
find_val_for_string(const char *needle, const enum_val *haystack,
|
||||||
|
gint default_value)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (haystack[i].name != NULL) {
|
||||||
|
if (strcasecmp(needle, haystack[i].name) == 0) {
|
||||||
|
return haystack[i].value;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
/* Takes an string and a pointer to an array of strings, and a default int value.
|
/* Takes an string and a pointer to an array of strings, and a default int value.
|
||||||
* The array must be terminated by a NULL string. If the string is found in the array
|
* The array must be terminated by a NULL string. If the string is found in the array
|
||||||
* of strings, the index of that string in the array is returned. Otherwise, the
|
* of strings, the index of that string in the array is returned. Otherwise, the
|
||||||
|
@ -167,24 +433,26 @@ print.file: /a/very/long/path/
|
||||||
#define MAX_VAL_LEN 1024
|
#define MAX_VAL_LEN 1024
|
||||||
|
|
||||||
#define DEF_NUM_COLS 6
|
#define DEF_NUM_COLS 6
|
||||||
|
|
||||||
|
static void read_prefs_file(const char *pf_path, FILE *pf);
|
||||||
|
|
||||||
e_prefs *
|
e_prefs *
|
||||||
read_prefs(char **pf_path_return) {
|
read_prefs(int *gpf_errno_return, char **gpf_path_return,
|
||||||
enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
|
int *pf_errno_return, char **pf_path_return)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
FILE *pf;
|
FILE *pf;
|
||||||
gchar cur_var[MAX_VAR_LEN], cur_val[MAX_VAL_LEN];
|
|
||||||
int got_c, state = START, i;
|
|
||||||
gint var_len = 0, val_len = 0, fline = 1, pline = 1;
|
|
||||||
gboolean got_val = FALSE;
|
|
||||||
fmt_data *cfmt;
|
fmt_data *cfmt;
|
||||||
gchar *col_fmt[] = {"No.", "%m", "Time", "%t",
|
gchar *col_fmt[] = {"No.", "%m", "Time", "%t",
|
||||||
"Source", "%s", "Destination", "%d",
|
"Source", "%s", "Destination", "%d",
|
||||||
"Protocol", "%p", "Info", "%i"};
|
"Protocol", "%p", "Info", "%i"};
|
||||||
|
|
||||||
|
|
||||||
/* Initialize preferences. With any luck, these values will be
|
|
||||||
overwritten below. */
|
|
||||||
if (init_prefs) {
|
if (init_prefs) {
|
||||||
init_prefs = 0;
|
/* Initialize preferences to wired-in default values.
|
||||||
|
They may be overridded by the global preferences file or the
|
||||||
|
user's preferences file. */
|
||||||
|
init_prefs = FALSE;
|
||||||
prefs.pr_format = PR_FMT_TEXT;
|
prefs.pr_format = PR_FMT_TEXT;
|
||||||
prefs.pr_dest = PR_DEST_CMD;
|
prefs.pr_dest = PR_DEST_CMD;
|
||||||
prefs.pr_file = g_strdup("ethereal.out");
|
prefs.pr_file = g_strdup("ethereal.out");
|
||||||
|
@ -220,19 +488,57 @@ read_prefs(char **pf_path_return) {
|
||||||
prefs.gui_ptree_expander_style = 1;
|
prefs.gui_ptree_expander_style = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the global preferences file, if it exists. */
|
||||||
|
*gpf_path_return = NULL;
|
||||||
|
if ((pf = fopen(GPF_PATH, "r")) != NULL) {
|
||||||
|
/* We succeeded in opening it; read it. */
|
||||||
|
read_prefs_file(GPF_PATH, pf);
|
||||||
|
fclose(pf);
|
||||||
|
} else {
|
||||||
|
/* We failed to open it. If we failed for some reason other than
|
||||||
|
"it doesn't exist", return the errno and the pathname, so our
|
||||||
|
caller can report the error. */
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
*gpf_errno_return = errno;
|
||||||
|
*gpf_path_return = GPF_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct the pathname of the user's preferences file. */
|
||||||
if (! pf_path) {
|
if (! pf_path) {
|
||||||
pf_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(PF_DIR) +
|
pf_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(PF_DIR) +
|
||||||
strlen(PF_NAME) + 4);
|
strlen(PF_NAME) + 4);
|
||||||
sprintf(pf_path, "%s/%s/%s", get_home_dir(), PF_DIR, PF_NAME);
|
sprintf(pf_path, "%s/%s/%s", get_home_dir(), PF_DIR, PF_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the user's preferences file, if it exists. */
|
||||||
*pf_path_return = NULL;
|
*pf_path_return = NULL;
|
||||||
if ((pf = fopen(pf_path, "r")) == NULL) {
|
if ((pf = fopen(pf_path, "r")) != NULL) {
|
||||||
if (errno != ENOENT)
|
/* We succeeded in opening it; read it. */
|
||||||
|
read_prefs_file(pf_path, pf);
|
||||||
|
fclose(pf);
|
||||||
|
} else {
|
||||||
|
/* We failed to open it. If we failed for some reason other than
|
||||||
|
"it doesn't exist", return the errno and the pathname, so our
|
||||||
|
caller can report the error. */
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
*pf_errno_return = errno;
|
||||||
*pf_path_return = pf_path;
|
*pf_path_return = pf_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &prefs;
|
return &prefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_prefs_file(const char *pf_path, FILE *pf)
|
||||||
|
{
|
||||||
|
enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
|
||||||
|
gchar cur_var[MAX_VAR_LEN], cur_val[MAX_VAL_LEN];
|
||||||
|
int got_c, state = START;
|
||||||
|
gboolean got_val = FALSE;
|
||||||
|
gint var_len = 0, val_len = 0, fline = 1, pline = 1;
|
||||||
|
|
||||||
while ((got_c = getc(pf)) != EOF) {
|
while ((got_c = getc(pf)) != EOF) {
|
||||||
if (got_c == '\n') {
|
if (got_c == '\n') {
|
||||||
state = START;
|
state = START;
|
||||||
|
@ -259,8 +565,17 @@ read_prefs(char **pf_path_return) {
|
||||||
if (got_val) {
|
if (got_val) {
|
||||||
cur_var[var_len] = '\0';
|
cur_var[var_len] = '\0';
|
||||||
cur_val[val_len] = '\0';
|
cur_val[val_len] = '\0';
|
||||||
if (! set_pref(cur_var, cur_val))
|
switch (set_pref(cur_var, cur_val)) {
|
||||||
g_warning ("%s line %d: Bogus preference", pf_path, pline);
|
|
||||||
|
case PREFS_SET_SYNTAX_ERR:
|
||||||
|
g_warning ("%s line %d: Syntax error", pf_path, pline);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREFS_SET_NO_SUCH_PREF:
|
||||||
|
g_warning ("%s line %d: No such preference \"%s\"", pf_path,
|
||||||
|
pline, cur_var);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_warning ("%s line %d: Incomplete preference", pf_path, pline);
|
g_warning ("%s line %d: Incomplete preference", pf_path, pline);
|
||||||
}
|
}
|
||||||
|
@ -311,15 +626,62 @@ read_prefs(char **pf_path_return) {
|
||||||
if (got_val) {
|
if (got_val) {
|
||||||
cur_var[var_len] = '\0';
|
cur_var[var_len] = '\0';
|
||||||
cur_val[val_len] = '\0';
|
cur_val[val_len] = '\0';
|
||||||
if (! set_pref(cur_var, cur_val))
|
switch (set_pref(cur_var, cur_val)) {
|
||||||
g_warning ("%s line %d: Bogus preference", pf_path, pline);
|
|
||||||
|
case PREFS_SET_SYNTAX_ERR:
|
||||||
|
g_warning ("%s line %d: Syntax error", pf_path, pline);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREFS_SET_NO_SUCH_PREF:
|
||||||
|
g_warning ("%s line %d: No such preference \"%s\"", pf_path,
|
||||||
|
pline, cur_var);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_warning ("%s line %d: Incomplete preference", pf_path, pline);
|
g_warning ("%s line %d: Incomplete preference", pf_path, pline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(pf);
|
}
|
||||||
|
|
||||||
return &prefs;
|
/*
|
||||||
|
* Given a string of the form "<pref name>:<pref value>", as might appear
|
||||||
|
* as an argument to a "-o" option, parse it and set the preference in
|
||||||
|
* question. Return an indication of whether it succeeded or failed
|
||||||
|
* in some fashion.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
prefs_set_pref(char *prefarg)
|
||||||
|
{
|
||||||
|
u_char *p, *colonp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
colonp = strchr(prefarg, ':');
|
||||||
|
if (colonp == NULL)
|
||||||
|
return PREFS_SET_SYNTAX_ERR;
|
||||||
|
|
||||||
|
p = colonp;
|
||||||
|
*p++ = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip over any white space (there probably won't be any, but
|
||||||
|
* as we allow it in the preferences file, we might as well
|
||||||
|
* allow it here).
|
||||||
|
*/
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
if (*p == '\0') {
|
||||||
|
/*
|
||||||
|
* Put the colon back, so if our caller uses, in an
|
||||||
|
* error message, the string they passed us, the message
|
||||||
|
* looks correct.
|
||||||
|
*/
|
||||||
|
*colonp = ':';
|
||||||
|
return PREFS_SET_SYNTAX_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_pref(prefarg, p);
|
||||||
|
*colonp = ':'; /* put the colon back */
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PRS_PRINT_FMT "print.format"
|
#define PRS_PRINT_FMT "print.format"
|
||||||
|
@ -344,36 +706,42 @@ read_prefs(char **pf_path_return) {
|
||||||
static gchar *pr_formats[] = { "text", "postscript" };
|
static gchar *pr_formats[] = { "text", "postscript" };
|
||||||
static gchar *pr_dests[] = { "command", "file" };
|
static gchar *pr_dests[] = { "command", "file" };
|
||||||
|
|
||||||
int
|
static int
|
||||||
set_pref(gchar *pref, gchar *value) {
|
set_pref(gchar *pref_name, gchar *value)
|
||||||
|
{
|
||||||
GList *col_l;
|
GList *col_l;
|
||||||
gint llen;
|
gint llen;
|
||||||
fmt_data *cfmt;
|
fmt_data *cfmt;
|
||||||
unsigned long int cval;
|
unsigned long int cval;
|
||||||
|
guint uval;
|
||||||
|
char *p;
|
||||||
|
gchar *dotp;
|
||||||
|
module_t *module;
|
||||||
|
pref_t *pref;
|
||||||
|
|
||||||
if (strcmp(pref, PRS_PRINT_FMT) == 0) {
|
if (strcmp(pref_name, PRS_PRINT_FMT) == 0) {
|
||||||
if (strcmp(value, pr_formats[PR_FMT_TEXT]) == 0) {
|
if (strcmp(value, pr_formats[PR_FMT_TEXT]) == 0) {
|
||||||
prefs.pr_format = PR_FMT_TEXT;
|
prefs.pr_format = PR_FMT_TEXT;
|
||||||
} else if (strcmp(value, pr_formats[PR_FMT_PS]) == 0) {
|
} else if (strcmp(value, pr_formats[PR_FMT_PS]) == 0) {
|
||||||
prefs.pr_format = PR_FMT_PS;
|
prefs.pr_format = PR_FMT_PS;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return PREFS_SET_SYNTAX_ERR;
|
||||||
}
|
}
|
||||||
} else if (strcmp(pref, PRS_PRINT_DEST) == 0) {
|
} else if (strcmp(pref_name, PRS_PRINT_DEST) == 0) {
|
||||||
if (strcmp(value, pr_dests[PR_DEST_CMD]) == 0) {
|
if (strcmp(value, pr_dests[PR_DEST_CMD]) == 0) {
|
||||||
prefs.pr_dest = PR_DEST_CMD;
|
prefs.pr_dest = PR_DEST_CMD;
|
||||||
} else if (strcmp(value, pr_dests[PR_DEST_FILE]) == 0) {
|
} else if (strcmp(value, pr_dests[PR_DEST_FILE]) == 0) {
|
||||||
prefs.pr_dest = PR_DEST_FILE;
|
prefs.pr_dest = PR_DEST_FILE;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return PREFS_SET_SYNTAX_ERR;
|
||||||
}
|
}
|
||||||
} else if (strcmp(pref, PRS_PRINT_FILE) == 0) {
|
} else if (strcmp(pref_name, PRS_PRINT_FILE) == 0) {
|
||||||
if (prefs.pr_file) g_free(prefs.pr_file);
|
if (prefs.pr_file) g_free(prefs.pr_file);
|
||||||
prefs.pr_file = g_strdup(value);
|
prefs.pr_file = g_strdup(value);
|
||||||
} else if (strcmp(pref, PRS_PRINT_CMD) == 0) {
|
} else if (strcmp(pref_name, PRS_PRINT_CMD) == 0) {
|
||||||
if (prefs.pr_cmd) g_free(prefs.pr_cmd);
|
if (prefs.pr_cmd) g_free(prefs.pr_cmd);
|
||||||
prefs.pr_cmd = g_strdup(value);
|
prefs.pr_cmd = g_strdup(value);
|
||||||
} else if (strcmp(pref, PRS_COL_FMT) == 0) {
|
} else if (strcmp(pref_name, PRS_COL_FMT) == 0) {
|
||||||
if ((col_l = get_string_list(value)) && (g_list_length(col_l) % 2) == 0) {
|
if ((col_l = get_string_list(value)) && (g_list_length(col_l) % 2) == 0) {
|
||||||
while (prefs.col_list) {
|
while (prefs.col_list) {
|
||||||
cfmt = prefs.col_list->data;
|
cfmt = prefs.col_list->data;
|
||||||
|
@ -396,66 +764,195 @@ set_pref(gchar *pref, gchar *value) {
|
||||||
/* To do: else print some sort of error? */
|
/* To do: else print some sort of error? */
|
||||||
}
|
}
|
||||||
clear_string_list(col_l);
|
clear_string_list(col_l);
|
||||||
} else if (strcmp(pref, PRS_STREAM_CL_FG) == 0) {
|
} else if (strcmp(pref_name, PRS_STREAM_CL_FG) == 0) {
|
||||||
cval = strtoul(value, NULL, 16);
|
cval = strtoul(value, NULL, 16);
|
||||||
prefs.st_client_fg.pixel = 0;
|
prefs.st_client_fg.pixel = 0;
|
||||||
prefs.st_client_fg.red = RED_COMPONENT(cval);
|
prefs.st_client_fg.red = RED_COMPONENT(cval);
|
||||||
prefs.st_client_fg.green = GREEN_COMPONENT(cval);
|
prefs.st_client_fg.green = GREEN_COMPONENT(cval);
|
||||||
prefs.st_client_fg.blue = BLUE_COMPONENT(cval);
|
prefs.st_client_fg.blue = BLUE_COMPONENT(cval);
|
||||||
} else if (strcmp(pref, PRS_STREAM_CL_BG) == 0) {
|
} else if (strcmp(pref_name, PRS_STREAM_CL_BG) == 0) {
|
||||||
cval = strtoul(value, NULL, 16);
|
cval = strtoul(value, NULL, 16);
|
||||||
prefs.st_client_bg.pixel = 0;
|
prefs.st_client_bg.pixel = 0;
|
||||||
prefs.st_client_bg.red = RED_COMPONENT(cval);
|
prefs.st_client_bg.red = RED_COMPONENT(cval);
|
||||||
prefs.st_client_bg.green = GREEN_COMPONENT(cval);
|
prefs.st_client_bg.green = GREEN_COMPONENT(cval);
|
||||||
prefs.st_client_bg.blue = BLUE_COMPONENT(cval);
|
prefs.st_client_bg.blue = BLUE_COMPONENT(cval);
|
||||||
} else if (strcmp(pref, PRS_STREAM_SR_FG) == 0) {
|
} else if (strcmp(pref_name, PRS_STREAM_SR_FG) == 0) {
|
||||||
cval = strtoul(value, NULL, 16);
|
cval = strtoul(value, NULL, 16);
|
||||||
prefs.st_server_fg.pixel = 0;
|
prefs.st_server_fg.pixel = 0;
|
||||||
prefs.st_server_fg.red = RED_COMPONENT(cval);
|
prefs.st_server_fg.red = RED_COMPONENT(cval);
|
||||||
prefs.st_server_fg.green = GREEN_COMPONENT(cval);
|
prefs.st_server_fg.green = GREEN_COMPONENT(cval);
|
||||||
prefs.st_server_fg.blue = BLUE_COMPONENT(cval);
|
prefs.st_server_fg.blue = BLUE_COMPONENT(cval);
|
||||||
} else if (strcmp(pref, PRS_STREAM_SR_BG) == 0) {
|
} else if (strcmp(pref_name, PRS_STREAM_SR_BG) == 0) {
|
||||||
cval = strtoul(value, NULL, 16);
|
cval = strtoul(value, NULL, 16);
|
||||||
prefs.st_server_bg.pixel = 0;
|
prefs.st_server_bg.pixel = 0;
|
||||||
prefs.st_server_bg.red = RED_COMPONENT(cval);
|
prefs.st_server_bg.red = RED_COMPONENT(cval);
|
||||||
prefs.st_server_bg.green = GREEN_COMPONENT(cval);
|
prefs.st_server_bg.green = GREEN_COMPONENT(cval);
|
||||||
prefs.st_server_bg.blue = BLUE_COMPONENT(cval);
|
prefs.st_server_bg.blue = BLUE_COMPONENT(cval);
|
||||||
} else if (strcmp(pref, PRS_GUI_SCROLLBAR_ON_RIGHT) == 0) {
|
} else if (strcmp(pref_name, PRS_GUI_SCROLLBAR_ON_RIGHT) == 0) {
|
||||||
if (strcmp(value, "TRUE") == 0) {
|
if (strcmp(value, "TRUE") == 0) {
|
||||||
prefs.gui_scrollbar_on_right = TRUE;
|
prefs.gui_scrollbar_on_right = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prefs.gui_scrollbar_on_right = FALSE;
|
prefs.gui_scrollbar_on_right = FALSE;
|
||||||
}
|
}
|
||||||
} else if (strcmp(pref, PRS_GUI_PLIST_SEL_BROWSE) == 0) {
|
} else if (strcmp(pref_name, PRS_GUI_PLIST_SEL_BROWSE) == 0) {
|
||||||
if (strcmp(value, "TRUE") == 0) {
|
if (strcmp(value, "TRUE") == 0) {
|
||||||
prefs.gui_plist_sel_browse = TRUE;
|
prefs.gui_plist_sel_browse = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prefs.gui_plist_sel_browse = FALSE;
|
prefs.gui_plist_sel_browse = FALSE;
|
||||||
}
|
}
|
||||||
} else if (strcmp(pref, PRS_GUI_PTREE_SEL_BROWSE) == 0) {
|
} else if (strcmp(pref_name, PRS_GUI_PTREE_SEL_BROWSE) == 0) {
|
||||||
if (strcmp(value, "TRUE") == 0) {
|
if (strcmp(value, "TRUE") == 0) {
|
||||||
prefs.gui_ptree_sel_browse = TRUE;
|
prefs.gui_ptree_sel_browse = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prefs.gui_ptree_sel_browse = FALSE;
|
prefs.gui_ptree_sel_browse = FALSE;
|
||||||
}
|
}
|
||||||
} else if (strcmp(pref, PRS_GUI_PTREE_LINE_STYLE) == 0) {
|
} else if (strcmp(pref_name, PRS_GUI_PTREE_LINE_STYLE) == 0) {
|
||||||
prefs.gui_ptree_line_style =
|
prefs.gui_ptree_line_style =
|
||||||
find_index_from_string_array(value, gui_ptree_line_style_text, 0);
|
find_index_from_string_array(value, gui_ptree_line_style_text, 0);
|
||||||
} else if (strcmp(pref, PRS_GUI_PTREE_EXPANDER_STYLE) == 0) {
|
} else if (strcmp(pref_name, PRS_GUI_PTREE_EXPANDER_STYLE) == 0) {
|
||||||
prefs.gui_ptree_expander_style =
|
prefs.gui_ptree_expander_style =
|
||||||
find_index_from_string_array(value, gui_ptree_expander_style_text, 1);
|
find_index_from_string_array(value, gui_ptree_expander_style_text, 1);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
/* To which module does this preference belong? */
|
||||||
|
dotp = strchr(pref_name, '.');
|
||||||
|
if (dotp == NULL)
|
||||||
|
return PREFS_SET_SYNTAX_ERR; /* no ".", so no module/name separator */
|
||||||
|
*dotp = '\0'; /* separate module and preference name */
|
||||||
|
module = find_module(pref_name);
|
||||||
|
*dotp = '.'; /* put the preference string back */
|
||||||
|
if (module == NULL)
|
||||||
|
return PREFS_SET_NO_SUCH_PREF; /* no such module */
|
||||||
|
dotp++; /* skip past separator to preference name */
|
||||||
|
pref = find_preference(module, dotp);
|
||||||
|
if (pref == NULL)
|
||||||
|
return PREFS_SET_NO_SUCH_PREF; /* no such preference */
|
||||||
|
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
uval = strtoul(value, &p, pref->info.base);
|
||||||
|
if (p == value || *p != '\0')
|
||||||
|
return PREFS_SET_SYNTAX_ERR; /* number was bad */
|
||||||
|
*pref->varp.uint = uval;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
/* XXX - give an error if it's neither "true" nor "false"? */
|
||||||
|
if (strcasecmp(value, "true") == 0)
|
||||||
|
*pref->varp.bool = TRUE;
|
||||||
|
else
|
||||||
|
*pref->varp.bool = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
/* XXX - give an error if it doesn't match? */
|
||||||
|
*pref->varp.enump = find_val_for_string(value,
|
||||||
|
pref->info.enum_info.enumvals, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
if (*pref->varp.string != NULL)
|
||||||
|
g_free(*pref->varp.string);
|
||||||
|
*pref->varp.string = g_strdup(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return PREFS_SET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
module_t *module;
|
||||||
|
FILE *pf;
|
||||||
|
} write_pref_arg_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write out a single preference.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
write_pref(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
pref_t *pref = data;
|
||||||
|
write_pref_arg_t *arg = user_data;
|
||||||
|
const enum_val *enum_valp;
|
||||||
|
const char *val_string;
|
||||||
|
|
||||||
|
fprintf(arg->pf, "\n# %s\n", pref->description);
|
||||||
|
|
||||||
|
switch (pref->type) {
|
||||||
|
|
||||||
|
case PREF_UINT:
|
||||||
|
switch (pref->info.base) {
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
fprintf(arg->pf, "# A decimal number.\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %u\n", arg->module->name,
|
||||||
|
pref->name, *pref->varp.uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
fprintf(arg->pf, "# An octal number.\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %#o\n", arg->module->name,
|
||||||
|
pref->name, *pref->varp.uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
fprintf(arg->pf, "# A hexadecimal number.\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %#x\n", arg->module->name,
|
||||||
|
pref->name, *pref->varp.uint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_BOOL:
|
||||||
|
fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
|
||||||
|
*pref->varp.bool ? "TRUE" : "FALSE");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_ENUM:
|
||||||
|
fprintf(arg->pf, "# One of: ");
|
||||||
|
enum_valp = pref->info.enum_info.enumvals;
|
||||||
|
val_string = NULL;
|
||||||
|
while (enum_valp->name != NULL) {
|
||||||
|
if (enum_valp->value == *pref->varp.enump)
|
||||||
|
val_string = enum_valp->name;
|
||||||
|
fprintf(arg->pf, "%s", enum_valp->name);
|
||||||
|
enum_valp++;
|
||||||
|
if (enum_valp->name == NULL)
|
||||||
|
fprintf(arg->pf, "\n");
|
||||||
|
else
|
||||||
|
fprintf(arg->pf, ", ");
|
||||||
|
}
|
||||||
|
fprintf(arg->pf, "# (case-insensitive).\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
|
||||||
|
val_string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREF_STRING:
|
||||||
|
fprintf(arg->pf, "# A string.\n");
|
||||||
|
fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
|
||||||
|
*pref->varp.string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_module_prefs(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
write_pref_arg_t arg;
|
||||||
|
|
||||||
|
arg.module = data;
|
||||||
|
arg.pf = user_data;
|
||||||
|
g_list_foreach(arg.module->prefs, write_pref, &arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
write_prefs(char **pf_path_return) {
|
write_prefs(char **pf_path_return)
|
||||||
|
{
|
||||||
FILE *pf;
|
FILE *pf;
|
||||||
struct stat s_buf;
|
struct stat s_buf;
|
||||||
|
|
||||||
|
@ -549,6 +1046,8 @@ write_prefs(char **pf_path_return) {
|
||||||
fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
|
fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
|
||||||
gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
|
gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
|
||||||
|
|
||||||
|
g_list_foreach(modules, write_module_prefs, pf);
|
||||||
|
|
||||||
fclose(pf);
|
fclose(pf);
|
||||||
|
|
||||||
/* XXX - catch I/O errors (e.g. "ran out of disk space") and return
|
/* XXX - catch I/O errors (e.g. "ran out of disk space") and return
|
||||||
|
|
93
prefs.h
93
prefs.h
|
@ -1,7 +1,7 @@
|
||||||
/* prefs.h
|
/* prefs.h
|
||||||
* Definitions for preference handling routines
|
* Definitions for preference handling routines
|
||||||
*
|
*
|
||||||
* $Id: prefs.h,v 1.15 2000/01/06 07:33:22 guy Exp $
|
* $Id: prefs.h,v 1.16 2000/07/05 09:40:42 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -50,7 +50,96 @@ typedef struct _e_prefs {
|
||||||
|
|
||||||
extern e_prefs prefs;
|
extern e_prefs prefs;
|
||||||
|
|
||||||
e_prefs* read_prefs(char **);
|
/*
|
||||||
|
* Routines to let modules that have preference settings register
|
||||||
|
* themselves by name, and to let them register preference settings
|
||||||
|
* by name.
|
||||||
|
*/
|
||||||
|
struct pref_module;
|
||||||
|
|
||||||
|
typedef struct pref_module module_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a module that will have preferences.
|
||||||
|
* Specify the name used for the module in the preferences file, the
|
||||||
|
* title used in the tab for it in a preferences dialog box, and a
|
||||||
|
* routine to call back when we apply the preferences.
|
||||||
|
*/
|
||||||
|
module_t *prefs_register_module(const char *name, const char *title,
|
||||||
|
void (*apply_cb)(void));
|
||||||
|
|
||||||
|
typedef void (*module_cb)(module_t *module, gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each module.
|
||||||
|
*/
|
||||||
|
void prefs_module_foreach(module_cb callback, gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call the "apply" callback function for each module.
|
||||||
|
*/
|
||||||
|
void prefs_apply_all(void);
|
||||||
|
|
||||||
|
struct preference;
|
||||||
|
|
||||||
|
typedef struct preference pref_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an unsigned integral value.
|
||||||
|
*/
|
||||||
|
void prefs_register_uint_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, guint base, guint *var);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an Boolean value.
|
||||||
|
*/
|
||||||
|
void prefs_register_bool_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, gboolean *var);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with an enumerated value.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
gint value;
|
||||||
|
} enum_val;
|
||||||
|
|
||||||
|
void prefs_register_enum_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, gint *var,
|
||||||
|
const enum_val *enumvals, gboolean radio_buttons);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a preference with a character-string value.
|
||||||
|
*/
|
||||||
|
void prefs_register_string_preference(module_t *module, const char *name,
|
||||||
|
const char *title, const char *description, char **var);
|
||||||
|
|
||||||
|
typedef void (*pref_cb)(pref_t *pref, gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each preference
|
||||||
|
* in a given module.
|
||||||
|
*/
|
||||||
|
void prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register all non-dissector modules' preferences.
|
||||||
|
*/
|
||||||
|
void prefs_register_modules(void);
|
||||||
|
|
||||||
|
e_prefs *read_prefs(int *, char **, int *, char **);
|
||||||
int write_prefs(char **);
|
int write_prefs(char **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a string of the form "<pref name>:<pref value>", as might appear
|
||||||
|
* as an argument to a "-o" option, parse it and set the preference in
|
||||||
|
* question. Return an indication of whether it succeeded or failed
|
||||||
|
* in some fashion.
|
||||||
|
*/
|
||||||
|
#define PREFS_SET_OK 0 /* succeeded */
|
||||||
|
#define PREFS_SET_SYNTAX_ERR 1 /* syntax error in string */
|
||||||
|
#define PREFS_SET_NO_SUCH_PREF 2 /* no such preference */
|
||||||
|
|
||||||
|
int prefs_set_pref(char *prefarg);
|
||||||
|
|
||||||
#endif /* prefs.h */
|
#endif /* prefs.h */
|
||||||
|
|
57
tethereal.c
57
tethereal.c
|
@ -1,6 +1,6 @@
|
||||||
/* tethereal.c
|
/* tethereal.c
|
||||||
*
|
*
|
||||||
* $Id: tethereal.c,v 1.33 2000/07/05 02:06:58 guy Exp $
|
* $Id: tethereal.c,v 1.34 2000/07/05 09:40:43 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -132,13 +132,13 @@ print_usage(void)
|
||||||
VERSION, comp_info_str);
|
VERSION, comp_info_str);
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <capture filter> ]\n", PACKAGE);
|
fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <capture filter> ]\n", PACKAGE);
|
||||||
fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ] [ -r infile ]\n");
|
fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
|
||||||
fprintf(stderr, "\t[ -R <read filter> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
|
fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
|
||||||
fprintf(stderr, "\t[ -w savefile ] [ -x ]\n");
|
fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ] [ -r infile ]\n", PACKAGE);
|
fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
|
||||||
fprintf(stderr, "\t[ -R <read filter> ] [ -t <time stamp format> ] [ -w savefile ]\n");
|
fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
|
||||||
fprintf(stderr, "\t[ -x ]\n");
|
fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
|
fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
|
||||||
for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
|
for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
|
||||||
|
@ -162,7 +162,8 @@ main(int argc, char *argv[])
|
||||||
extern char pcap_version[];
|
extern char pcap_version[];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
char *pf_path;
|
char *gpf_path, *pf_path;
|
||||||
|
int gpf_open_errno, pf_open_errno;
|
||||||
int err;
|
int err;
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
gboolean capture_filter_specified = FALSE;
|
gboolean capture_filter_specified = FALSE;
|
||||||
|
@ -177,13 +178,22 @@ main(int argc, char *argv[])
|
||||||
dfilter *rfcode = NULL;
|
dfilter *rfcode = NULL;
|
||||||
e_prefs *prefs;
|
e_prefs *prefs;
|
||||||
|
|
||||||
|
/* Register all dissectors; we must do this before checking for the
|
||||||
|
"-G" flag, as the "-G" flag dumps a list of fields registered
|
||||||
|
by the dissectors, and we must do it before we read the preferences,
|
||||||
|
in case any dissectors register preferences. */
|
||||||
|
dissect_init();
|
||||||
|
|
||||||
|
/* Now register the preferences for any non-dissector modules.
|
||||||
|
We must do that before we read the preferences as well. */
|
||||||
|
prefs_register_modules();
|
||||||
|
|
||||||
/* If invoked with the "-G" flag, we dump out a glossary of
|
/* If invoked with the "-G" flag, we dump out a glossary of
|
||||||
display filter symbols.
|
display filter symbols.
|
||||||
|
|
||||||
We do this here to mirror what happens in the GTK+ version, although
|
We do this here to mirror what happens in the GTK+ version, although
|
||||||
it's not necessary here. */
|
it's not necessary here. */
|
||||||
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
|
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
|
||||||
dissect_init();
|
|
||||||
proto_registrar_dump();
|
proto_registrar_dump();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -191,10 +201,14 @@ main(int argc, char *argv[])
|
||||||
/* Set the C-language locale to the native environment. */
|
/* Set the C-language locale to the native environment. */
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
prefs = read_prefs(&pf_path);
|
prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
|
||||||
|
if (gpf_path != NULL) {
|
||||||
|
fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
|
||||||
|
strerror(gpf_open_errno));
|
||||||
|
}
|
||||||
if (pf_path != NULL) {
|
if (pf_path != NULL) {
|
||||||
fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
|
fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
|
||||||
strerror(errno));
|
strerror(pf_open_errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the capture file struct */
|
/* Initialize the capture file struct */
|
||||||
|
@ -266,7 +280,7 @@ main(int argc, char *argv[])
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Now get our args */
|
/* Now get our args */
|
||||||
while ((opt = getopt(argc, argv, "c:Df:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
|
while ((opt = getopt(argc, argv, "c:Df:F:hi:no:r:R:s:t:vw:Vx")) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c': /* Capture xxx packets */
|
case 'c': /* Capture xxx packets */
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
|
@ -311,6 +325,21 @@ main(int argc, char *argv[])
|
||||||
case 'n': /* No name resolution */
|
case 'n': /* No name resolution */
|
||||||
g_resolving_actif = 0;
|
g_resolving_actif = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'o': /* Override preference from command line */
|
||||||
|
switch (prefs_set_pref(optarg)) {
|
||||||
|
|
||||||
|
case PREFS_SET_SYNTAX_ERR:
|
||||||
|
fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREFS_SET_NO_SUCH_PREF:
|
||||||
|
fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
|
||||||
|
optarg);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'r': /* Read capture file xxx */
|
case 'r': /* Read capture file xxx */
|
||||||
cf_name = g_strdup(optarg);
|
cf_name = g_strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -407,8 +436,6 @@ main(int argc, char *argv[])
|
||||||
else if (cfile.snap < MIN_PACKET_SIZE)
|
else if (cfile.snap < MIN_PACKET_SIZE)
|
||||||
cfile.snap = MIN_PACKET_SIZE;
|
cfile.snap = MIN_PACKET_SIZE;
|
||||||
|
|
||||||
dissect_init(); /* Init anything that needs initializing */
|
|
||||||
|
|
||||||
if (rfilter != NULL) {
|
if (rfilter != NULL) {
|
||||||
if (dfilter_compile(rfilter, &rfcode) != 0) {
|
if (dfilter_compile(rfilter, &rfcode) != 0) {
|
||||||
fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
|
fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
|
||||||
|
|
Loading…
Reference in New Issue