Add a "report_failure()" routine to allow dissectors to report arbitrary

errors to the user.  Use that, rather than "g_warning()", in the
Diameter dissector to report errors reading the dictionary.

Make the format argument to "simple_dialog()" a "const" pointer.

Fix up the read-error message in Tethereal to end with a newline.

If a simple dialog is requested before the main window or the
capture-control window is popped up, queue it up and pop the queued
messages up once the main or capture-control window is displayed.

svn path=/trunk/; revision=10616
This commit is contained in:
Guy Harris 2004-04-16 23:17:13 +00:00
parent a0146ed5be
commit d209115ba3
16 changed files with 202 additions and 69 deletions

View File

@ -2,7 +2,7 @@
* Routines to put up various "standard" alert boxes used in multiple
* places
*
* $Id: alert_box.c,v 1.5 2004/03/23 21:19:55 guy Exp $
* $Id: alert_box.c,v 1.6 2004/04/16 23:16:28 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -38,6 +38,15 @@
#include "simple_dialog.h"
/*
* Alert box for general errors.
*/
void
failure_alert_box(const char *msg_format, va_list ap)
{
vsimple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg_format, ap);
}
/*
* Alert box for a failed attempt to open or create a file.
* "err" is assumed to be a UNIX-style errno; "for_writing" is TRUE if
@ -65,7 +74,7 @@ void
read_failure_alert_box(const char *filename, int err)
{
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"An error occurred while reading from the file \"%s\": %s.",
"An error occurred while reading from the file \"%s\": %s.",
filename, strerror(err));
}

View File

@ -2,7 +2,7 @@
* Routines to put up various "standard" alert boxes used in multiple
* places
*
* $Id: alert_box.h,v 1.4 2004/03/23 21:19:55 guy Exp $
* $Id: alert_box.h,v 1.5 2004/04/16 23:16:28 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -30,6 +30,11 @@
extern "C" {
#endif /* __cplusplus */
/*
* Alert box for general errors.
*/
extern void failure_alert_box(const char *msg_format, va_list ap);
/*
* Alert box for a failed attempt to open or create a file.
* "err" is assumed to be a UNIX-style errno; "for_writing" is TRUE if

View File

@ -1,6 +1,6 @@
/* epan.h
*
* $Id: epan.c,v 1.24 2004/03/23 21:19:56 guy Exp $
* $Id: epan.c,v 1.25 2004/04/16 23:16:28 guy Exp $
*
* Ethereal Protocol Analyzer Library
*/
@ -22,6 +22,7 @@
#include "../tap.h"
#include "resolv.h"
static void (*report_failure_func)(const char *, va_list);
static void (*report_open_failure_func)(const char *, int, gboolean);
static void (*report_read_failure_func)(const char *, int);
@ -49,9 +50,11 @@ static void (*report_read_failure_func)(const char *, int);
void
epan_init(const char *plugin_dir, void (*register_all_protocols)(void),
void (*register_all_handoffs)(void),
void (*report_failure)(const char *, va_list),
void (*report_open_failure)(const char *, int, gboolean),
void (*report_read_failure)(const char *, int))
{
report_failure_func = report_failure;
report_open_failure_func = report_open_failure;
report_read_failure_func = report_read_failure;
except_init();
@ -90,7 +93,23 @@ epan_circuit_init(void)
}
/*
* Report an error when trying to open a file.
* Report a general error.
*/
void
report_failure(const char *msg_format, ...)
{
va_list ap;
va_start(ap, msg_format);
(*report_failure_func)(msg_format, ap);
va_end(ap);
}
/*
* Report an error when trying to open or create a file.
* "err" is assumed to be an error code from Wiretap; positive values are
* UNIX-style errnos, so this can be used for open failures not from
* Wiretap as long as the failue code is just an errno.
*/
void
report_open_failure(const char *filename, int err,
@ -101,6 +120,7 @@ report_open_failure(const char *filename, int err,
/*
* Report an error when trying to read a file.
* "err" is assumed to be a UNIX-style errno.
*/
void
report_read_failure(const char *filename, int err)

View File

@ -1,6 +1,6 @@
/* epan.h
*
* $Id: epan.h,v 1.16 2004/03/23 21:19:56 guy Exp $
* $Id: epan.h,v 1.17 2004/04/16 23:16:28 guy Exp $
*
* Ethereal Protocol Analyzer Library
*
@ -34,6 +34,7 @@ typedef struct _epan_dissect_t epan_dissect_t;
void epan_init(const char * plugindir, void (*register_all_protocols)(void),
void (*register_all_handoffs)(void),
void (*report_failure)(const char *, va_list),
void (*report_open_failure)(const char *, int, gboolean),
void (*report_read_failure)(const char *, int));
void epan_cleanup(void);

View File

@ -2,7 +2,7 @@
* Declarations of routines for dissectors to use to report errors to
* the user (e.g., problems with preference settings)
*
* $Id: report_err.h,v 1.1 2004/03/23 21:19:56 guy Exp $
* $Id: report_err.h,v 1.2 2004/04/16 23:16:28 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -41,6 +41,11 @@ extern void report_open_failure(const char *filename, int err,
*/
extern void report_read_failure(const char *filename, int err);
/*
* Report a general error.
*/
extern void report_failure(const char *msg_format, ...);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.422 2004/04/06 19:02:18 ulfl Exp $
* $Id: main.c,v 1.423 2004/04/16 23:16:29 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -1940,7 +1940,7 @@ main(int argc, char *argv[])
dissectors, and we must do it before we read the preferences, in
case any dissectors register preferences. */
epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
open_failure_alert_box, read_failure_alert_box);
failure_alert_box,open_failure_alert_box,read_failure_alert_box);
/* Register all tap listeners; we do this before we parse the arguments,
as the "-z" argument can specify a registered tap. */
@ -2694,6 +2694,9 @@ main(int argc, char *argv[])
we were told to. */
create_main_window(pl_size, tv_size, bv_size, prefs);
/* Pop up any queued-up alert boxes. */
display_queued_messages();
/* Read the recent file, as we have the gui now ready for it. */
read_recent(&rf_path, &rf_open_errno);
@ -2808,6 +2811,9 @@ main(int argc, char *argv[])
}
#endif
/* Pop up any queued-up alert boxes. */
display_queued_messages();
/* If the global preferences file exists but we failed to open it
or had an error reading 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

View File

@ -1,7 +1,7 @@
/* simple_dialog.c
* Simple message dialog box routines.
*
* $Id: simple_dialog.c,v 1.30 2004/03/13 15:30:08 ulfl Exp $
* $Id: simple_dialog.c,v 1.31 2004/04/16 23:16:29 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -45,35 +45,26 @@ static void simple_dialog_cancel_cb(GtkWidget *, gpointer);
#define CALLBACK_BTN_KEY "ESD_Callback_Btn"
#define CALLBACK_DATA_KEY "ESD_Callback_Data"
/* Simple dialog function - Displays a dialog box with the supplied message
* text.
*
* Args:
* type : One of ESD_TYPE_*.
* btn_mask : The value passed in determines which buttons are displayed.
* msg_format : Sprintf-style format of the text displayed in the dialog.
* ... : Argument list for msg_format
*
*
* XXX - if we haven't yet put up the main window, we should just
* queue up the message, etc., and wait until the main window pops up
* (or until we figure out that we're in a capture child and aren't
* going to pop up a main window) and pop up the alert boxes then, so
* that even stuff popped up before we put up the main window (such
* as file-open or file-read errors from dissectors' init routines)
* shows up on top.
/*
* Queue for messages requested before we have a main window.
*/
typedef struct {
gint type;
gint btn_mask;
char *message;
} queued_message_t;
static GSList *message_queue;
gpointer
simple_dialog(gint type, gint btn_mask, gchar *msg_format, ...) {
static GtkWidget *
display_simple_dialog(gint type, gint btn_mask, char *message)
{
GtkWidget *win, *main_vb, *top_hb, *type_pm, *msg_label,
*bbox, *ok_bt, *bt;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkStyle *style;
GdkColormap *cmap;
va_list ap;
gchar message[2048];
gchar **icon;
/* Main window */
@ -156,11 +147,6 @@ simple_dialog(gint type, gint btn_mask, gchar *msg_format, ...) {
gtk_container_add(GTK_CONTAINER(top_hb), type_pm);
gtk_widget_show(type_pm);
/* Load our vararg list into the message string */
va_start(ap, msg_format);
g_vsnprintf(message, sizeof(message), msg_format, ap);
va_end(ap);
msg_label = gtk_label_new(message);
#if GTK_MAJOR_VERSION >= 2
@ -240,6 +226,78 @@ simple_dialog(gint type, gint btn_mask, gchar *msg_format, ...) {
return win;
}
void
display_queued_messages(void)
{
queued_message_t *queued_message;
while (message_queue != NULL) {
queued_message = message_queue->data;
message_queue = g_slist_remove(message_queue, queued_message);
display_simple_dialog(queued_message->type, queued_message->btn_mask,
queued_message->message);
g_free(queued_message->message);
g_free(queued_message);
}
}
/* Simple dialog function - Displays a dialog box with the supplied message
* text.
*
* Args:
* type : One of ESD_TYPE_*.
* btn_mask : The value passed in determines which buttons are displayed.
* msg_format : Sprintf-style format of the text displayed in the dialog.
* ... : Argument list for msg_format
*/
gpointer
vsimple_dialog(gint type, gint btn_mask, const gchar *msg_format, va_list ap)
{
gchar *message;
queued_message_t *queued_message;
GtkWidget *win;
/* Format the message. */
message = g_strdup_vprintf(msg_format, ap);
/* If we don't yet have a main window, queue up the message for later
display. */
if (top_level == NULL) {
queued_message = g_malloc(sizeof (queued_message_t));
queued_message->type = type;
queued_message->btn_mask = btn_mask;
queued_message->message = message;
message_queue = g_slist_append(message_queue, queued_message);
return NULL;
}
/*
* Do we have any queued up messages? If so, pop them up.
*/
display_queued_messages();
win = display_simple_dialog(type, btn_mask, message);
g_free(message);
return win;
}
gpointer
simple_dialog(gint type, gint btn_mask, const gchar *msg_format, ...)
{
va_list ap;
gpointer ret;
va_start(ap, msg_format);
ret = vsimple_dialog(type, btn_mask, msg_format, ap);
va_end(ap);
return ret;
}
static void
simple_dialog_cancel_cb(GtkWidget *w, gpointer win) {
gint button = GPOINTER_TO_INT( OBJECT_GET_DATA(w, CALLBACK_BTN_KEY));
@ -268,5 +326,3 @@ char *
simple_dialog_primary_end(void) {
return PRIMARY_TEXT_END;
}

View File

@ -1,7 +1,7 @@
/* packet-diameter.c
* Routines for Diameter packet disassembly
*
* $Id: packet-diameter.c,v 1.65 2004/03/23 21:19:55 guy Exp $
* $Id: packet-diameter.c,v 1.66 2004/04/16 23:16:28 guy Exp $
*
* Copyright (c) 2001 by David Frascone <dave@frascone.com>
*
@ -322,7 +322,7 @@ xmlParseFilePush( char *filename, int checkValid) {
/* Check valid */
if (!valid) {
g_warning( "Error! Invalid xml in %s! Failed DTD check!",
report_failure( "Error! Invalid xml in %s! Failed DTD check!",
filename);
return NULL;
}
@ -411,7 +411,7 @@ xmlParseAVP(xmlNodePtr cur)
valueCode = XmlStub.xmlGetProp(cur, "code");
if (!valueName || !valueCode) {
g_warning( "Error, bad value on avp %s", name);
report_failure( "Error, bad value on avp %s", name);
return (-1);
}
@ -440,11 +440,11 @@ xmlParseAVP(xmlNodePtr cur)
}
if (TypeValues[i].strptr == NULL) {
g_warning( "Invalid Type field in dictionary! avp %s (%s)", name, type);
report_failure( "Invalid Type field in dictionary! avp %s (%s)", name, type);
return (-1);
}
} else if (!vEntry) {
g_warning("Missing type/enum field in dictionary avpName=%s",
report_failure("Missing type/enum field in dictionary avpName=%s",
name);
return (-1);
}
@ -486,7 +486,7 @@ addCommand(int code, char *name, char *vendorId)
entry = (CommandCode *) g_malloc(sizeof (CommandCode));
if (entry == NULL) {
g_warning("Unable to allocate memory");
report_failure("Unable to allocate memory");
return (-1);
}
@ -523,7 +523,7 @@ xmlParseCommand(xmlNodePtr cur)
name = XmlStub.xmlGetProp(cur, "name");
code = XmlStub.xmlGetProp(cur, "code");
if (!name || !code) {
g_warning("Invalid command. Name or code missing!");
report_failure("Invalid command. Name or code missing!");
return -1;
}
vendorIdString = XmlStub.xmlGetProp(cur, "vendor-id");
@ -542,14 +542,14 @@ dictionaryAddApplication(char *name, int id)
ApplicationId *entry;
if (!name || (id < 0) || (id == 0 && !allow_zero_as_app_id)) {
g_warning( "Diameter Error: Invalid application (name=%p, id=%d)",
report_failure( "Diameter Error: Invalid application (name=%p, id=%d)",
name, id);
return (-1);
} /* Sanity Checks */
entry = g_malloc(sizeof(ApplicationId));
if (!entry) {
g_warning( "Unable to allocate memory");
report_failure( "Unable to allocate memory");
return (-1);
}
@ -600,7 +600,7 @@ xmlParseVendor(xmlNodePtr cur)
code = XmlStub.xmlGetProp(cur, "code");
if (!id || !name || !code) {
g_warning( "Invalid vendor section. vendor-id, name, and code must be specified");
report_failure( "Invalid vendor section. vendor-id, name, and code must be specified");
return -1;
}
@ -623,7 +623,7 @@ xmlDictionaryParseSegment(xmlNodePtr cur, int base)
if (!name || !id) {
/* ERROR!!! */
g_warning("Diameter: Invalid application!: name=\"%s\", id=\"%s\"",
report_failure("Diameter: Invalid application!: name=\"%s\", id=\"%s\"",
name?name:"NULL", id?id:"NULL");
return -1;
}
@ -657,7 +657,7 @@ xmlDictionaryParseSegment(xmlNodePtr cur, int base)
/* WORK -- parse in valid types . . . */
} else {
/* IF we got here, we're an error */
g_warning("Error! expecting an avp or a typedefn (got \"%s\")",
report_failure("Error! expecting an avp or a typedefn (got \"%s\")",
cur->name);
return (-1);
}
@ -686,7 +686,7 @@ xmlDictionaryParse(xmlNodePtr cur)
} else if (strcasecmp(cur->name, "comment") == 0) {
/* Ignore text */
} else {
g_warning( "Diameter: XML Expecting a base or an application (got \"%s\")",
report_failure( "Diameter: XML Expecting a base or an application (got \"%s\")",
cur->name);
return (-1);
}
@ -715,7 +715,7 @@ loadXMLDictionary(void)
/* Check for invalid xml */
if (doc == NULL) {
g_warning("Diameter: Unable to parse xmldictionary %s",
report_failure("Diameter: Unable to parse xmldictionary %s",
gbl_diameterDictionary);
return -1;
}
@ -725,13 +725,13 @@ loadXMLDictionary(void)
*/
cur = XmlStub.xmlDocGetRootElement(doc);
if (cur == NULL) {
g_warning("Diameter: Error: \"%s\": empty document",
report_failure("Diameter: Error: \"%s\": empty document",
gbl_diameterDictionary);
XmlStub.xmlFreeDoc(doc);
return -1;
}
if (XmlStub.xmlStrcmp(cur->name, (const xmlChar *) "dictionary")) {
g_warning("Diameter: Error: \"%s\": document of the wrong type, root node != dictionary",
report_failure("Diameter: Error: \"%s\": document of the wrong type, root node != dictionary",
gbl_diameterDictionary);
XmlStub.xmlFreeDoc(doc);
return -1;
@ -801,7 +801,7 @@ initializeDictionary(void)
if (loadLibXML() ||
(loadXMLDictionary() != 0)) {
/* Something failed. Use the static dictionary */
g_warning("Diameter: Using static dictionary! (Unable to use XML)");
report_failure("Diameter: Using static dictionary! (Unable to use XML)");
initializeDictionaryDefaults();
}
} /* initializeDictionary */
@ -1949,4 +1949,3 @@ proto_register_diameter(void)
prefs_register_obsolete_preference(diameter_module, "udp.port");
prefs_register_obsolete_preference(diameter_module, "command_in_header");
} /* proto_register_diameter */

View File

@ -80,4 +80,5 @@ dissect_ber_sequence, dissect_ber_sequence_of, dissect_ber_set_of,
dissect_ber_octet_string, dissect_ber_bitstring, dissect_ber_restricted_string,
dissect_ber_object_identifier, get_ber_identifier, get_ber_length,
proto_item_get_subtree, proto_tree_get_parent, proto_item_get_parent,
proto_item_get_parent_nth, get_ber_last_created_item,
proto_item_get_parent_nth, get_ber_last_created_item, report_failure,

View File

@ -273,3 +273,4 @@ p_proto_tree_get_parent = pat->p_proto_tree_get_parent;
p_proto_item_get_parent = pat->p_proto_item_get_parent;
p_proto_item_get_parent_nth = pat->p_proto_item_get_parent_nth;
p_get_ber_last_created_item = pat->p_get_ber_last_created_item;
p_report_failure = pat->p_report_failure;

View File

@ -273,3 +273,4 @@
#define proto_item_get_parent (*p_proto_item_get_parent)
#define proto_item_get_parent_nth (*p_proto_item_get_parent_nth)
#define get_ber_last_created_item (*p_get_ber_last_created_item)
#define report_failure (*p_report_failure)

View File

@ -273,3 +273,4 @@ addr_proto_tree_get_parent p_proto_tree_get_parent;
addr_proto_item_get_parent p_proto_item_get_parent;
addr_proto_item_get_parent_nth p_proto_item_get_parent_nth;
addr_get_ber_last_created_item p_get_ber_last_created_item;
addr_report_failure p_report_failure;

View File

@ -273,3 +273,4 @@ typedef proto_item *(*addr_proto_tree_get_parent) (proto_tree *);
typedef proto_item *(*addr_proto_item_get_parent) (proto_item *);
typedef proto_item *(*addr_proto_item_get_parent_nth) (proto_item *, int);
typedef proto_item *(*addr_get_ber_last_created_item) (void);
typedef void (*addr_report_failure) (const char *, ...);

View File

@ -1,7 +1,7 @@
/* plugin_api_list.c
* Used to generate various included files for plugin API
*
* $Id: plugin_api_list.c,v 1.33 2004/03/25 23:55:21 guy Exp $
* $Id: plugin_api_list.c,v 1.34 2004/04/16 23:16:29 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -434,3 +434,6 @@ proto_item* proto_tree_get_parent(proto_tree *tree);
proto_item* proto_item_get_parent(proto_item *ti);
proto_item* proto_item_get_parent_nth(proto_item *ti, int gen);
proto_item *get_ber_last_created_item(void);
void report_failure(const char *msg_format, ...);

View File

@ -2,7 +2,7 @@
* Definitions for alert box routines with toolkit-independent APIs but
* toolkit-dependent implementations.
*
* $Id: simple_dialog.h,v 1.11 2004/02/12 22:24:27 guy Exp $
* $Id: simple_dialog.h,v 1.12 2004/04/16 23:16:28 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -60,10 +60,16 @@ extern "C" {
/* show a simple dialog */
#if __GNUC__ >= 2
extern gpointer simple_dialog(gint type, gint btn_mask, gchar *msg_format, ...)
extern gpointer simple_dialog(gint type, gint btn_mask,
const gchar *msg_format, ...)
__attribute__((format (printf, 3, 4)));
extern gpointer vsimple_dialog(gint type, gint btn_mask,
const gchar *msg_format, va_list ap);
#else
extern gpointer simple_dialog(gint type, gint btn_mask, gchar *msg_format, ...);
extern gpointer simple_dialog(gint type, gint btn_mask,
const gchar *msg_format, ...);
extern gpointer vsimple_dialog(gint type, gint btn_mask,
const gchar *msg_format, va_list ap);
#endif
/* callback function type */
@ -75,6 +81,14 @@ extern void simple_dialog_set_cb(gpointer dialog, simple_dialog_cb_t callback_fc
extern char *simple_dialog_primary_start(void);
extern char *simple_dialog_primary_end(void);
/*
* If a routine is called to display a dialog before there are any windows
* open, information to use to display the dialog is queued up. This
* routine should be called once there are windows open, so that the queued
* up dialogs are displayed on top of those windows.
*/
extern void display_queued_messages(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1,6 +1,6 @@
/* tethereal.c
*
* $Id: tethereal.c,v 1.234 2004/04/16 18:17:47 ulfl Exp $
* $Id: tethereal.c,v 1.235 2004/04/16 23:16:28 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -187,6 +187,7 @@ static int pipe_dispatch(int, loop_data *, struct pcap_hdr *, \
static void open_failure_message(const char *filename, int err,
gboolean for_writing);
static void failure_message(const char *msg_format, va_list ap);
static void read_failure_message(const char *filename, int err);
capture_file cfile;
@ -840,7 +841,7 @@ main(int argc, char *argv[])
dissectors, and we must do it before we read the preferences, in
case any dissectors register preferences. */
epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
open_failure_message, read_failure_message);
failure_message,open_failure_message,read_failure_message);
/* Register all tap listeners; we do this before we parse the arguments,
as the "-z" argument can specify a registered tap. */
@ -2977,11 +2978,9 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
static void
open_failure_message(const char *filename, int err, gboolean for_writing)
{
char *errmsg;
errmsg = g_strdup_printf(file_open_error_message(err, for_writing), filename);
fprintf(stderr, "tethereal: %s\n", errmsg);
g_free(errmsg);
fprintf(stderr, "tethereal: ");
fprintf(stderr, file_open_error_message(err, for_writing), filename);
fprintf(stderr, "\n");
}
int
@ -3329,12 +3328,23 @@ pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
#endif /* _WIN32 */
#endif /* HAVE_LIBPCAP */
/*
* General errors are reported with an console message in Tethereal.
*/
static void
failure_message(const char *msg_format, va_list ap)
{
fprintf(stderr, "tethereal: ");
vfprintf(stderr, msg_format, ap);
fprintf(stderr, "\n");
}
/*
* Read errors are reported with an console message in Tethereal.
*/
static void
read_failure_message(const char *filename, int err)
{
fprintf(stderr, "tethereal: An error occurred while reading from the file \"%s\": %s.",
fprintf(stderr, "tethereal: An error occurred while reading from the file \"%s\": %s.\n",
filename, strerror(err));
}