From 757c90f2a618287ff92fd6a1b929a3278d8f3bef Mon Sep 17 00:00:00 2001 From: Michal Toman Date: Mon, 7 Mar 2011 12:37:42 +0100 Subject: retrace server: guess release if 'os_release' file is missing --- src/retrace/retrace.py | 12 ++++++++++++ src/retrace/worker.py | 45 ++++++++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/retrace/retrace.py b/src/retrace/retrace.py index 46adb740..cc67f62f 100644 --- a/src/retrace/retrace.py +++ b/src/retrace/retrace.py @@ -25,6 +25,10 @@ RELEASE_PARSERS = { "fedora": re.compile("^Fedora[^0-9]+([0-9]+)[^\(]\(([^\)]+)\)$"), } +GUESS_RELEASE_PARSERS = { + "fedora": re.compile("\.fc([0-9]+)"), +} + TASKPASS_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" CONFIG_FILE = "/etc/abrt/retrace.conf" @@ -109,6 +113,14 @@ def guess_arch(coredump_path): return None +def guess_release(package): + for distro in GUESS_RELEASE_PARSERS.keys(): + match = GUESS_RELEASE_PARSERS[distro].search(package) + if match: + return distro, match.group(1) + + return None, None + def gen_task_password(taskdir): generator = random.SystemRandom() taskpass = "" diff --git a/src/retrace/worker.py b/src/retrace/worker.py index 2bb33237..f7381c72 100755 --- a/src/retrace/worker.py +++ b/src/retrace/worker.py @@ -68,6 +68,16 @@ if __name__ == "__main__": LOG.close() sys.exit(16) + # read package file + try: + package_file = open("%s/crash/package" % savedir, "r") + crash_package = package_file.read() + package_file.close() + except Exception as ex: + LOG.write("Unable to read crash package from 'package' file: %s.\n" % ex) + LOG.close() + sys.exit(17) + # read release, distribution and version from release file release_path = "%s/crash/os_release" % savedir if not os.path.isfile(release_path): @@ -77,23 +87,28 @@ if __name__ == "__main__": release_file = open(release_path, "r") release = release_file.read() release_file.close() - except Exception as ex: - LOG.write("Unable to read distribution and version from 'release' file: %s.\n" % ex) - LOG.close() - sys.exit(17) - version = distribution = None - for distro in RELEASE_PARSERS.keys(): - match = RELEASE_PARSERS[distro].match(release) - if match: - version = match.group(1) - distribution = distro - break + version = distribution = None + for distro in RELEASE_PARSERS.keys(): + match = RELEASE_PARSERS[distro].match(release) + if match: + version = match.group(1) + distribution = distro + break - if not version or not distribution: - LOG.write("Release '%s' is not supported.\n" % release) - LOG.close() - sys.exit(18) + if not version or not distribution: + raise Exception, "Release '%s' is not supported.\n" + + except Exception as ex: + LOG.write("Unable to read distribution and version from 'release' file: %s.\n" % ex) + LOG.write("Trying to guess distribution and version... ") + distribution, version = guess_release(crash_package) + if distribution and version: + LOG.write("%s-%s\n" % (distribution, version)) + else: + LOG.write("Failure\n") + LOG.close() + sys.exit(18) # read package file try: -- cgit From f2e2bba844ed36ab3b9ce0c936dad673cfc865b9 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 15:36:07 +0100 Subject: added function to parse event description from xml file --- src/include/Makefile.am | 3 +- src/include/abrtlib.h | 3 + src/include/report/event_xml_parser.h | 41 ++++++++ src/lib/Makefile.am | 3 +- src/lib/event_xml_parser.c | 186 ++++++++++++++++++++++++++++++++++ 5 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 src/include/report/event_xml_parser.h create mode 100644 src/lib/event_xml_parser.c diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 477963c3..e21b043b 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -2,7 +2,8 @@ libreport_includedir = $(includedir)/report libreport_include_HEADERS = \ report/crash_data.h \ report/dump_dir.h \ - report/run_event.h + report/run_event.h \ + report/event_xml_parser.h libabrt_includedir = $(includedir)/abrt libabrt_include_HEADERS = \ diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h index 116f4b36..1b2f6bbc 100644 --- a/src/include/abrtlib.h +++ b/src/include/abrtlib.h @@ -82,6 +82,7 @@ int vdprintf(int d, const char *format, va_list ap); #include "abrt_types.h" #include "dump_dir.h" #include "run_event.h" +#include "event_xml_parser.h" #ifdef __cplusplus @@ -256,6 +257,8 @@ void parse_release_for_rhts(const char *pRelease, char **product, char **version #define load_conf_file abrt_load_conf_file bool load_conf_file(const char *pPath, map_string_h *settings, bool skipKeysWithoutValue); +void load_event_description_from_file(event_obj_t *event_desc, const char* filename); + /* Tries to create a copy of dump_dir_name in base_dir, with same or similar basename. * Returns NULL if copying failed. In this case, logs a message before returning. */ #define steal_directory abrt_steal_directory diff --git a/src/include/report/event_xml_parser.h b/src/include/report/event_xml_parser.h new file mode 100644 index 00000000..caf81506 --- /dev/null +++ b/src/include/report/event_xml_parser.h @@ -0,0 +1,41 @@ +#include + +typedef enum +{ + OPTION_TYPE_TEXT, + OPTION_TYPE_BOOL, + OPTION_TYPE_PASSWORD, + OPTION_TYPE_NUMBER, + OPTION_TYPE_INVALID, +} option_type_t; + +/* + * struct to hold information about config options + * it's supposed to hold information about: + * type -> which designates the widget used to display it and we can do some test based on the type + * label + * allowed value(s) -> regexp? + * name -> env variable name + * value -> value retrieved from the gui, so when we want to set the env + * evn variables, we can just traverse the list of the options + * and set the env variables according to name:value in this structure + */ +typedef struct +{ + const char* label; + const char* name; //name of the value which should be used for env variable + char *value; + option_type_t type; + const char* description; //can be used as tooltip in gtk app + const char* allowed_value; + int required; +} event_option_obj_t; + +//structure to hold the option data +typedef struct +{ + const char *name; //name of the event "Bugzilla" "RedHat Support Uploader" + const char *title; //window title - not used right now, maybe the "name" is enough? + const char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" + GList *options; +} event_obj_t; diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index bad3e63a..9e9a7324 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -43,7 +43,8 @@ libreport_la_SOURCES = \ hooklib.c hooklib.h \ parse_release.c \ parse_options.c parse_options.h \ - steal_directory.c + steal_directory.c \ + event_xml_parser.c libreport_la_CPPFLAGS = \ -Wall -Werror \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c new file mode 100644 index 00000000..6b562957 --- /dev/null +++ b/src/lib/event_xml_parser.c @@ -0,0 +1,186 @@ +//#include +#include +#include +#include +#include "event_xml_parser.h" + +#define EVENT_ELEMENT "event" +#define LABEL_ELEMENT "label" +#define DESCRIPTION_ELEMENT "description" +#define ALLOW_EMPTY_ELEMENT "allow-empty" +#define OPTION_ELEMENT "option" +#define ACTION_ELEMENT "action" +#define NAME_ELEMENT "name" + +int in_option = 0; + +static const char *option_types[] = +{ + "text", + "bool", + "password", + "number", + NULL +}; + +// Called for open tags +void start_element(GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + //g_print("start: %s\n", element_name); + + event_obj_t *ui = (event_obj_t *)user_data; + + if(strcmp(element_name, OPTION_ELEMENT) == 0) + { + if(in_option == 0) + { + in_option = 1; + event_option_obj_t *option = (event_option_obj_t *)malloc(sizeof(event_option_obj_t)); + //we need to prepend, so ui->options always points to the last created option + ui->options = g_list_prepend(ui->options, option); + + int i; + for(i = 0; attribute_names[i] != NULL; ++i) + { + //g_print("attr: %s:%s\n", attribute_names[i], attribute_values[i]); + if(strcmp(attribute_names[i], "name") == 0) + option->name = strdup(attribute_values[i]); + if(strcmp(attribute_names[i], "type") == 0) + { + option_type_t type = 0; + for(type = OPTION_TYPE_TEXT; type < OPTION_TYPE_INVALID; ++type) + { + if(strcmp(option_types[type], attribute_values[i]) == 0) + option->type = type; + } + } + } + } + else + { + g_print("error, option nested in option!\n"); + exit(-127); + } + } + +} + + // Called for close tags +void end_element(GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + event_obj_t *ui = (event_obj_t *)user_data; + if(strcmp(element_name, OPTION_ELEMENT) == 0) + { + in_option = 0; + } + if(strcmp(element_name, EVENT_ELEMENT) == 0) + { + //we need to revers the list, because we we're prepending + ui->options = g_list_reverse(ui->options); + in_option = 0; + } +} + + // Called for character data + // text is not nul-terminated +void text(GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + event_obj_t *ui = (event_obj_t *)user_data; + const gchar * inner_element = g_markup_parse_context_get_element(context); + char *_text = (char *)malloc(text_len+1); + strncpy(_text, text, text_len); + _text[text_len] = '\0'; + if(in_option == 1) + { + event_option_obj_t *option = (event_option_obj_t *)((ui->options)->data); + if(strcmp(inner_element, LABEL_ELEMENT) == 0) + { + //g_print("\tnew label: \t\t%s\n", _text); + option->label = _text; + } + if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) + { + //g_print("\ttooltip: \t\t%s\n", _text); + option->description = _text; + } + } + else + { + /* we're not in option, so the description is for the event */ + if(strcmp(inner_element, ACTION_ELEMENT) == 0) + { + //g_print("\taction description: \t%s\n", _text); + ui->action = _text; + } + if(strcmp(inner_element, NAME_ELEMENT) == 0) + { + //g_print("\tevent name: \t\t%s\n", _text); + ui->name = _text; + } + } + //will be freed when the event_option is freed + //free(_text); +} + + // Called for strings that should be re-saved verbatim in this same + // position, but are not otherwise interpretable. At the moment + // this includes comments and processing instructions. + // text is not nul-terminated +void passthrough(GMarkupParseContext *context, + const gchar *passthrough_text, + gsize text_len, + gpointer user_data, + GError **error) +{ + g_print("passthrough\n"); +} + +// Called on error, including one set by other +// methods in the vtable. The GError should not be freed. +void error(GMarkupParseContext *context, + GError *error, + gpointer user_data) +{ + g_print("error\n"); +} + +/* this function takes 2 parameters + * ui -> pointer to event_obj_t + * filename -> filename to read + * event_obj_t contains list of options, which is malloced by hits function + * and must be freed by the caller + */ + +void load_event_from_file(event_obj_t *ui, const char* filename) +{ + GMarkupParser parser; + parser.start_element = &start_element; + parser.end_element = &end_element; + parser.text = &text; + parser.passthrough = &passthrough; + parser.error = &error; + GMarkupParseContext *context = g_markup_parse_context_new( + &parser, G_MARKUP_TREAT_CDATA_AS_TEXT, + ui, NULL); + FILE* fin = fopen(filename, "r"); + size_t read_bytes = 0; + char buff[1024] = {'\0'}; + while((read_bytes = fread(buff, 1, 1024, fin))) + { + g_markup_parse_context_parse(context, buff, read_bytes, NULL); + } + fclose(fin); + free(context); +} -- cgit From bad8487bf919ba4b221b7be065c346221943812c Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 15:47:54 +0100 Subject: minor build fixes --- src/include/abrtlib.h | 2 -- src/include/report/event_xml_parser.h | 2 ++ src/lib/event_xml_parser.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h index 1b2f6bbc..6122f467 100644 --- a/src/include/abrtlib.h +++ b/src/include/abrtlib.h @@ -257,8 +257,6 @@ void parse_release_for_rhts(const char *pRelease, char **product, char **version #define load_conf_file abrt_load_conf_file bool load_conf_file(const char *pPath, map_string_h *settings, bool skipKeysWithoutValue); -void load_event_description_from_file(event_obj_t *event_desc, const char* filename); - /* Tries to create a copy of dump_dir_name in base_dir, with same or similar basename. * Returns NULL if copying failed. In this case, logs a message before returning. */ #define steal_directory abrt_steal_directory diff --git a/src/include/report/event_xml_parser.h b/src/include/report/event_xml_parser.h index caf81506..47852c67 100644 --- a/src/include/report/event_xml_parser.h +++ b/src/include/report/event_xml_parser.h @@ -39,3 +39,5 @@ typedef struct const char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" GList *options; } event_obj_t; + +void load_event_description_from_file(event_obj_t *event_desc, const char* filename); \ No newline at end of file diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index 6b562957..d429291f 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -163,7 +163,7 @@ void error(GMarkupParseContext *context, * and must be freed by the caller */ -void load_event_from_file(event_obj_t *ui, const char* filename) +void load_event_description_from_file(event_obj_t *ui, const char* filename) { GMarkupParser parser; parser.start_element = &start_element; -- cgit From 507caa094b0ecfe4f6f6a829887712d7c8174ae2 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 15:48:48 +0100 Subject: abrt-gtk: added function to dynamically generate the config dialog from event description --- src/gui-gtk/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui-gtk/Makefile.am b/src/gui-gtk/Makefile.am index a0d0de40..30d4f755 100644 --- a/src/gui-gtk/Makefile.am +++ b/src/gui-gtk/Makefile.am @@ -2,6 +2,7 @@ bin_PROGRAMS = abrt-gtk abrt_gtk_SOURCES = \ abrt-gtk.h abrt-gtk.c \ + event_config_dialog.c \ main.c abrt_gtk_CFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -- cgit From 4af44e92c689fe442dddbf6e18e2731e2d479c5a Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 15:59:00 +0100 Subject: event_xml_parser: string fields shouldn't be const, moved name and value higher in the structure --- src/include/report/event_xml_parser.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/include/report/event_xml_parser.h b/src/include/report/event_xml_parser.h index 47852c67..c6bda9d5 100644 --- a/src/include/report/event_xml_parser.h +++ b/src/include/report/event_xml_parser.h @@ -22,21 +22,21 @@ typedef enum */ typedef struct { - const char* label; - const char* name; //name of the value which should be used for env variable + char *name; //name of the value which should be used for env variable char *value; + char *label; option_type_t type; - const char* description; //can be used as tooltip in gtk app - const char* allowed_value; + char *description; //can be used as tooltip in gtk app + char *allowed_value; int required; } event_option_obj_t; //structure to hold the option data typedef struct { - const char *name; //name of the event "Bugzilla" "RedHat Support Uploader" - const char *title; //window title - not used right now, maybe the "name" is enough? - const char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" + char *name; //name of the event "Bugzilla" "RedHat Support Uploader" + char *title; //window title - not used right now, maybe the "name" is enough? + char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" GList *options; } event_obj_t; -- cgit From d18a48afc602a19130d13af6097df566fa260690 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 16:11:33 +0100 Subject: event_option_obj_t -> event_option_t, event_obj_t -> event_config_t --- src/include/report/event_xml_parser.h | 6 +++--- src/lib/event_xml_parser.c | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/include/report/event_xml_parser.h b/src/include/report/event_xml_parser.h index c6bda9d5..8e55b1b0 100644 --- a/src/include/report/event_xml_parser.h +++ b/src/include/report/event_xml_parser.h @@ -29,7 +29,7 @@ typedef struct char *description; //can be used as tooltip in gtk app char *allowed_value; int required; -} event_option_obj_t; +} event_option_t; //structure to hold the option data typedef struct @@ -38,6 +38,6 @@ typedef struct char *title; //window title - not used right now, maybe the "name" is enough? char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" GList *options; -} event_obj_t; +} event_config_t; -void load_event_description_from_file(event_obj_t *event_desc, const char* filename); \ No newline at end of file +void load_event_description_from_file(event_config_t *event_config, const char* filename); \ No newline at end of file diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index d429291f..da56a51c 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -33,14 +33,14 @@ void start_element(GMarkupParseContext *context, { //g_print("start: %s\n", element_name); - event_obj_t *ui = (event_obj_t *)user_data; + event_config_t *ui = (event_config_t *)user_data; if(strcmp(element_name, OPTION_ELEMENT) == 0) { if(in_option == 0) { in_option = 1; - event_option_obj_t *option = (event_option_obj_t *)malloc(sizeof(event_option_obj_t)); + event_option_t *option = (event_option_t *)malloc(sizeof(event_option_t)); //we need to prepend, so ui->options always points to the last created option ui->options = g_list_prepend(ui->options, option); @@ -76,7 +76,7 @@ void end_element(GMarkupParseContext *context, gpointer user_data, GError **error) { - event_obj_t *ui = (event_obj_t *)user_data; + event_config_t *ui = (event_config_t *)user_data; if(strcmp(element_name, OPTION_ELEMENT) == 0) { in_option = 0; @@ -97,14 +97,14 @@ void text(GMarkupParseContext *context, gpointer user_data, GError **error) { - event_obj_t *ui = (event_obj_t *)user_data; + event_config_t *ui = (event_config_t *)user_data; const gchar * inner_element = g_markup_parse_context_get_element(context); char *_text = (char *)malloc(text_len+1); strncpy(_text, text, text_len); _text[text_len] = '\0'; if(in_option == 1) { - event_option_obj_t *option = (event_option_obj_t *)((ui->options)->data); + event_option_t *option = (event_option_t *)((ui->options)->data); if(strcmp(inner_element, LABEL_ELEMENT) == 0) { //g_print("\tnew label: \t\t%s\n", _text); @@ -157,13 +157,13 @@ void error(GMarkupParseContext *context, } /* this function takes 2 parameters - * ui -> pointer to event_obj_t + * ui -> pointer to event_config_t * filename -> filename to read - * event_obj_t contains list of options, which is malloced by hits function + * event_config_t contains list of options, which is malloced by hits function * and must be freed by the caller */ -void load_event_description_from_file(event_obj_t *ui, const char* filename) +void load_event_description_from_file(event_config_t *event_config, const char* filename) { GMarkupParser parser; parser.start_element = &start_element; @@ -173,7 +173,7 @@ void load_event_description_from_file(event_obj_t *ui, const char* filename) parser.error = &error; GMarkupParseContext *context = g_markup_parse_context_new( &parser, G_MARKUP_TREAT_CDATA_AS_TEXT, - ui, NULL); + event_config, NULL); FILE* fin = fopen(filename, "r"); size_t read_bytes = 0; char buff[1024] = {'\0'}; -- cgit From 67541b83a1c09ad95ed497da3f90c8bf8ce40676 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Mon, 7 Mar 2011 16:56:33 +0100 Subject: fix build, there is no file event_config_dialog.c Signed-off-by: Nikola Pajkovsky --- src/gui-gtk/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui-gtk/Makefile.am b/src/gui-gtk/Makefile.am index 30d4f755..a0d0de40 100644 --- a/src/gui-gtk/Makefile.am +++ b/src/gui-gtk/Makefile.am @@ -2,7 +2,6 @@ bin_PROGRAMS = abrt-gtk abrt_gtk_SOURCES = \ abrt-gtk.h abrt-gtk.c \ - event_config_dialog.c \ main.c abrt_gtk_CFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -- cgit From 75d2a56b6420fd65f596b8ee18b02e121147ea4e Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 17:09:43 +0100 Subject: renamed some files, no code changes --- src/gui-gtk/Makefile.am | 1 + src/gui-gtk/event_config_dialog.c | 112 ++++++++++++++++++++++++++++++++++ src/include/Makefile.am | 2 +- src/include/abrtlib.h | 2 +- src/include/report/event_config.h | 51 ++++++++++++++++ src/include/report/event_xml_parser.h | 43 ------------- src/lib/event_xml_parser.c | 2 +- 7 files changed, 167 insertions(+), 46 deletions(-) create mode 100644 src/gui-gtk/event_config_dialog.c create mode 100644 src/include/report/event_config.h delete mode 100644 src/include/report/event_xml_parser.h diff --git a/src/gui-gtk/Makefile.am b/src/gui-gtk/Makefile.am index a0d0de40..30d4f755 100644 --- a/src/gui-gtk/Makefile.am +++ b/src/gui-gtk/Makefile.am @@ -2,6 +2,7 @@ bin_PROGRAMS = abrt-gtk abrt_gtk_SOURCES = \ abrt-gtk.h abrt-gtk.c \ + event_config_dialog.c \ main.c abrt_gtk_CFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ diff --git a/src/gui-gtk/event_config_dialog.c b/src/gui-gtk/event_config_dialog.c new file mode 100644 index 00000000..36f311c8 --- /dev/null +++ b/src/gui-gtk/event_config_dialog.c @@ -0,0 +1,112 @@ +#include "abrtlib.h" +#include + +static GtkWidget *option_table; +static int last_row = 0; + +GtkWidget *gtk_label_new_justify_left(const gchar *label_str) +{ + GtkWidget *label = gtk_label_new(label_str); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment(GTK_MISC(label), /*xalign:*/ 0, /*yalign:*/ 0.5); + return label; +} + +void add_option_to_dialog(event_option_t *option) +{ + + GtkWidget *label; + GtkWidget *option_input; + GtkWidget *option_hbox = gtk_hbox_new(FALSE, 0); + switch(option->type) + { + case OPTION_TYPE_TEXT: + case OPTION_TYPE_NUMBER: + label = gtk_label_new_justify_left(option->label); + gtk_table_attach(GTK_TABLE(option_table), label, + 0, 1, + last_row, last_row+1, + GTK_FILL, GTK_FILL, + 0,0); + option_input = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(option_table), option_input, + 1, 2, + last_row, last_row+1, + GTK_FILL, GTK_FILL, + 0,0); + + break; + case OPTION_TYPE_BOOL: + option_input = gtk_check_button_new_with_label(option->label); + gtk_table_attach(GTK_TABLE(option_table), option_input, + 0, 2, + last_row, last_row+1, + GTK_FILL, GTK_FILL, + 0,0); + break; + case OPTION_TYPE_PASSWORD: + label = gtk_label_new_justify_left(option->label); + gtk_table_attach(GTK_TABLE(option_table), label, + 0, 1, + last_row, last_row+1, + GTK_FILL, GTK_FILL, + 0,0); + option_input = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(option_table), option_input, + 1, 2, + last_row, last_row+1, + GTK_FILL, GTK_FILL, + 0,0); + + gtk_entry_set_visibility(GTK_ENTRY(option_input), 0); + break; + default: + option_input = gtk_label_new_justify_left("WTF?"); + g_print("unsupported option type\n"); + } + last_row++; + + gtk_widget_show_all(GTK_WIDGET(option_hbox)); +} + +void print_option(gpointer data, gpointer user_data) +{ + event_option_t * option = (event_option_t *)data; + /* + g_print("option:\n"); + g_print("\tlabel: %s\n", option->label); + g_print("\tenv name: %s\n", option->name); + g_print("\ttooltip: %s\n", option->description); + g_print("\ttype: %i\n", option->type); + */ + add_option_to_dialog(option); +} + +void show_event_config_dialog(const char* event_name) +{ + event_config_t ui; + ui.options = NULL; + load_event_description_from_file(&ui, "Bugzilla.xml"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( + ui.name, + NULL, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, + GTK_RESPONSE_APPLY, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + NULL); + int length = g_list_length(ui.options); + //g_print("%i\n", length); + option_table = gtk_table_new(length, 2, 0); + g_list_foreach(ui.options, &print_option, NULL); + GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_box_pack_start(GTK_BOX(content), option_table, 0, 0, 10); + gtk_widget_show_all(option_table); + int result = gtk_dialog_run(GTK_DIALOG(dialog)); + if(result == GTK_RESPONSE_APPLY) + g_print("apply\n"); + else if(result == GTK_RESPONSE_CANCEL) + g_print("cancel\n"); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} diff --git a/src/include/Makefile.am b/src/include/Makefile.am index e21b043b..e6f0387b 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -3,7 +3,7 @@ libreport_include_HEADERS = \ report/crash_data.h \ report/dump_dir.h \ report/run_event.h \ - report/event_xml_parser.h + report/event_config.h libabrt_includedir = $(includedir)/abrt libabrt_include_HEADERS = \ diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h index 6122f467..435c4def 100644 --- a/src/include/abrtlib.h +++ b/src/include/abrtlib.h @@ -82,7 +82,7 @@ int vdprintf(int d, const char *format, va_list ap); #include "abrt_types.h" #include "dump_dir.h" #include "run_event.h" -#include "event_xml_parser.h" +#include "event_config.h" #ifdef __cplusplus diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h new file mode 100644 index 00000000..ee0cf7ab --- /dev/null +++ b/src/include/report/event_config.h @@ -0,0 +1,51 @@ +#include + +typedef enum +{ + OPTION_TYPE_TEXT, + OPTION_TYPE_BOOL, + OPTION_TYPE_PASSWORD, + OPTION_TYPE_NUMBER, + OPTION_TYPE_INVALID, +} option_type_t; + +/* + * struct to hold information about config options + * it's supposed to hold information about: + * type -> which designates the widget used to display it and we can do some test based on the type + * label + * allowed value(s) -> regexp? + * name -> env variable name + * value -> value retrieved from the gui, so when we want to set the env + * evn variables, we can just traverse the list of the options + * and set the env variables according to name:value in this structure + */ +typedef struct +{ + char *name; //name of the value which should be used for env variable + char *value; + char *label; + option_type_t type; + char *description; //can be used as tooltip in gtk app + char *allowed_value; + int required; +} event_option_t; + +//structure to hold the option data +typedef struct +{ + char *name; //name of the event "Bugzilla" "RedHat Support Uploader" + char *title; //window title - not used right now, maybe the "name" is enough? + char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" + GList *options; +} event_config_t; + +void load_event_description_from_file(event_config_t *event_config, const char* filename); + +// (Re)loads data from /etc/abrt/events/*.{conf,xml} +void load_event_config_data(void); +/* Frees all loaded data */ +void free_event_config_data(void); +event_config_t *get_event_config(const char *name); + +extern GList *g_event_config_list; // for iterating through entire list of all loaded configs \ No newline at end of file diff --git a/src/include/report/event_xml_parser.h b/src/include/report/event_xml_parser.h deleted file mode 100644 index 8e55b1b0..00000000 --- a/src/include/report/event_xml_parser.h +++ /dev/null @@ -1,43 +0,0 @@ -#include - -typedef enum -{ - OPTION_TYPE_TEXT, - OPTION_TYPE_BOOL, - OPTION_TYPE_PASSWORD, - OPTION_TYPE_NUMBER, - OPTION_TYPE_INVALID, -} option_type_t; - -/* - * struct to hold information about config options - * it's supposed to hold information about: - * type -> which designates the widget used to display it and we can do some test based on the type - * label - * allowed value(s) -> regexp? - * name -> env variable name - * value -> value retrieved from the gui, so when we want to set the env - * evn variables, we can just traverse the list of the options - * and set the env variables according to name:value in this structure - */ -typedef struct -{ - char *name; //name of the value which should be used for env variable - char *value; - char *label; - option_type_t type; - char *description; //can be used as tooltip in gtk app - char *allowed_value; - int required; -} event_option_t; - -//structure to hold the option data -typedef struct -{ - char *name; //name of the event "Bugzilla" "RedHat Support Uploader" - char *title; //window title - not used right now, maybe the "name" is enough? - char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" - GList *options; -} event_config_t; - -void load_event_description_from_file(event_config_t *event_config, const char* filename); \ No newline at end of file diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index da56a51c..7b9edc4f 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -2,7 +2,7 @@ #include #include #include -#include "event_xml_parser.h" +#include "event_config.h" #define EVENT_ELEMENT "event" #define LABEL_ELEMENT "label" -- cgit From 1292529dafdca6543ce9e85d383effb2c566b79a Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Mon, 7 Mar 2011 17:25:15 +0100 Subject: add license and #ifdef EVENT_CONFIG_H around header Signed-off-by: Nikola Pajkovsky --- src/include/report/event_config.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h index ee0cf7ab..e4710dcf 100644 --- a/src/include/report/event_config.h +++ b/src/include/report/event_config.h @@ -1,5 +1,26 @@ +/* + Copyright (C) 2011 ABRT team + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + #include +#ifndef EVENT_CONFIG_H +#define EVENT_CONFIG_H + typedef enum { OPTION_TYPE_TEXT, @@ -48,4 +69,6 @@ void load_event_config_data(void); void free_event_config_data(void); event_config_t *get_event_config(const char *name); -extern GList *g_event_config_list; // for iterating through entire list of all loaded configs \ No newline at end of file +extern GList *g_event_config_list; // for iterating through entire list of all loaded configs + +#endif -- cgit From 62890f4365ce10d71d1e122aec1d65566825b1f6 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Mon, 7 Mar 2011 17:32:37 +0100 Subject: added event_config.c stub --- src/include/report/event_config.h | 2 +- src/lib/Makefile.am | 3 ++- src/lib/event_config.c | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/lib/event_config.c diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h index ee0cf7ab..3d05a2c9 100644 --- a/src/include/report/event_config.h +++ b/src/include/report/event_config.h @@ -48,4 +48,4 @@ void load_event_config_data(void); void free_event_config_data(void); event_config_t *get_event_config(const char *name); -extern GList *g_event_config_list; // for iterating through entire list of all loaded configs \ No newline at end of file +extern GHashTable *g_event_config_list; // for iterating through entire list of all loaded configs \ No newline at end of file diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 9e9a7324..4f800a0e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -44,7 +44,8 @@ libreport_la_SOURCES = \ parse_release.c \ parse_options.c parse_options.h \ steal_directory.c \ - event_xml_parser.c + event_xml_parser.c \ + event_config.c libreport_la_CPPFLAGS = \ -Wall -Werror \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ diff --git a/src/lib/event_config.c b/src/lib/event_config.c new file mode 100644 index 00000000..77cbaf4b --- /dev/null +++ b/src/lib/event_config.c @@ -0,0 +1,26 @@ +#include "event_config.h" + +GHashTable *g_event_config_list; + +// (Re)loads data from /etc/abrt/events/*.{conf,xml} +void load_event_config_data(void) +{ + /* for each xml file call load_event_description_from_file */ + /* for each conf file call load_even_options_value_from_file? + * - we don't have this + * - should re-use the event_config structure created when parsing xml - if exists + * - or should this one be called first? + */ +} +/* Frees all loaded data */ +void free_event_config_data(void) +{ + +} + +event_config_t *get_event_config(const char *name) +{ + //could g_event_config_list be null? + gpointer event_config = g_hash_table_lookup(g_event_config_list, name); + return event_config; +} -- cgit From ef47609ab73ba222e0ef9f2da51dca4650af69d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 7 Mar 2011 21:49:51 +0100 Subject: gui-wizard-gtk: add code to export/unexport config variables. Untested Signed-off-by: Denys Vlasenko --- src/cli/report.cpp | 10 ++---- src/daemon/MiddleWare.cpp | 10 ++---- src/gui-wizard-gtk/wizard.c | 85 +++++++++++++++++++++++++++++++++++++-------- src/include/xfuncs.h | 13 +++++++ src/lib/xfuncs.c | 14 ++++++++ 5 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/cli/report.cpp b/src/cli/report.cpp index ff18d19c..ebbe8e0b 100644 --- a/src/cli/report.cpp +++ b/src/cli/report.cpp @@ -649,14 +649,8 @@ static int run_events(const char *dump_dir_name, for (GList *li = env_list; li; li = g_list_next(li)) { char *s = (char*)li->data; - /* Need to make a copy: just cutting s at '=' and unsetenv'ing - * the result would be a bug! s _itself_ is in environment now, - * we must not modify it there! - */ - char *name = xstrndup(s, strchrnul(s, '=') - s); - VERB3 log("Unexporting '%s'", name); - unsetenv(name); - free(name); + VERB3 log("Unexporting '%s'", s); + safe_unsetenv(s); free(s); } g_list_free(env_list); diff --git a/src/daemon/MiddleWare.cpp b/src/daemon/MiddleWare.cpp index 215e7b49..8d62c697 100644 --- a/src/daemon/MiddleWare.cpp +++ b/src/daemon/MiddleWare.cpp @@ -351,14 +351,8 @@ report_status_t Report(crash_data_t *client_report, for (GList *li = env_list; li; li = g_list_next(li)) { char *s = (char*)li->data; - /* Need to make a copy: just cutting s at '=' and unsetenv'ing - * the result would be a bug! s _itself_ is in environment now, - * we must not modify it there! - */ - char *name = xstrndup(s, strchrnul(s, '=') - s); - VERB3 log("Unexporting '%s'", name); - unsetenv(name); - free(name); + VERB3 log("Unexporting '%s'", s); + safe_unsetenv(s); free(s); } g_list_free(env_list); diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c index 07ce4ed7..1df70625 100644 --- a/src/gui-wizard-gtk/wizard.c +++ b/src/gui-wizard-gtk/wizard.c @@ -237,6 +237,23 @@ static void save_text_from_text_view(GtkTextView *tv, const char *name) free(new_str); } +static void append_to_textview(GtkTextView *tv, const char *str, int len) +{ + GtkTextBuffer *tb = gtk_text_view_get_buffer(tv); + + /* Ensure we insert text at the end */ + GtkTextIter text_iter; + gtk_text_buffer_get_iter_at_offset(tb, &text_iter, -1); + gtk_text_buffer_place_cursor(tb, &text_iter); + + gtk_text_buffer_insert_at_cursor(tb, str, len >= 0 ? len : strlen(str)); + + /* Scroll so that the end of the log is visible */ + gtk_text_buffer_get_iter_at_offset(tb, &text_iter, -1); + gtk_text_view_scroll_to_iter(tv, &text_iter, + /*within_margin:*/ 0.0, /*use_align:*/ FALSE, /*xalign:*/ 0, /*yalign:*/ 0); +} + /* update_gui_state_from_crash_data */ @@ -453,6 +470,7 @@ struct analyze_event_data struct run_event_state *run_state; const char *event_name; GList *more_events; + GList *env_list; GtkWidget *page_widget; GtkLabel *status_label; GtkTextView *tv_log; @@ -462,21 +480,52 @@ struct analyze_event_data /*guint event_source_id;*/ }; -static void append_to_textview(GtkTextView *tv, const char *str, int len) +static GList *export_event_config(const char *event_name) { - GtkTextBuffer *tb = gtk_text_view_get_buffer(tv); + GList *env_list = NULL; - /* Ensure we insert text at the end */ - GtkTextIter text_iter; - gtk_text_buffer_get_iter_at_offset(tb, &text_iter, -1); - gtk_text_buffer_place_cursor(tb, &text_iter); + GHashTableIter iter; + char *name; + event_config_t *cfg; + g_hash_table_iter_init(&iter, g_event_config_list); + while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&cfg)) + { + if (strcmp(cfg->name, event_name) != 0) + continue; + for (GList *lopt = cfg->options; lopt; lopt = lopt->next) + { + event_option_t *opt = lopt->data; + char *var_val = xasprintf("%s=%s", opt->name, opt->value); +VERB3 log("Exporting '%s'", var_val); + env_list = g_list_prepend(env_list, var_val); + putenv(var_val); + } + } + return env_list; +} - gtk_text_buffer_insert_at_cursor(tb, str, len >= 0 ? len : strlen(str)); +static void unexport_event_config(GList *env_list) +{ + while (env_list) + { + char *var_val = env_list->data; +VERB3 log("Unexporting '%s'", var_val); + safe_unsetenv(var_val); + env_list = g_list_remove(env_list, var_val); + free(var_val); + } +} - /* Scroll so that the end of the log is visible */ - gtk_text_buffer_get_iter_at_offset(tb, &text_iter, -1); - gtk_text_view_scroll_to_iter(tv, &text_iter, - /*within_margin:*/ 0.0, /*use_align:*/ FALSE, /*xalign:*/ 0, /*yalign:*/ 0); +static int spawn_next_command_in_evd(struct analyze_event_data *evd) +{ + evd->env_list = export_event_config(evd->event_name); + int r = spawn_next_command(evd->run_state, g_dump_dir_name, evd->event_name); + if (r < 0) + { + unexport_event_config(evd->env_list); + evd->env_list = NULL; + } + return r; } static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, gpointer data) @@ -492,7 +541,7 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g } if (r < 0 && errno == EAGAIN) - /* We got all data, but fd is still open. Done for now */ + /* We got all buffered data, but fd is still open. Done for now */ return TRUE; /* "please don't remove this event (yet)" */ /* EOF/error. Wait for child to actually exit, collect status */ @@ -502,9 +551,12 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g if (WIFSIGNALED(status)) retval = WTERMSIG(status) + 128; + unexport_event_config(evd->env_list); + evd->env_list = NULL; + /* Stop if exit code is not 0, or no more commands */ if (retval != 0 - || spawn_next_command(evd->run_state, g_dump_dir_name, evd->event_name) < 0 + || spawn_next_command_in_evd(evd) < 0 ) { VERB1 log("done running event on '%s': %d", g_dump_dir_name, retval); //append_to_textview(evd->tv_log, msg); @@ -534,7 +586,7 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g evd->more_events = g_list_remove(evd->more_events, evd->more_events->data); if (prepare_commands(evd->run_state, g_dump_dir_name, evd->event_name) != 0 - && spawn_next_command(evd->run_state, g_dump_dir_name, evd->event_name) >= 0 + && spawn_next_command_in_evd(evd) >= 0 ) { VERB1 log("running event '%s' on '%s'", evd->event_name, g_dump_dir_name); break; @@ -589,8 +641,12 @@ static void start_event_run(const char *event_name, if (!locked) return; /* user refused to steal, or write error, etc... */ + GList *env_list = export_event_config(event_name); if (spawn_next_command(state, g_dump_dir_name, event_name) < 0) + { + unexport_event_config(env_list); goto no_cmds; + } VERB1 log("running event '%s' on '%s'", event_name, g_dump_dir_name); @@ -601,6 +657,7 @@ static void start_event_run(const char *event_name, evd->run_state = state; evd->event_name = event_name; evd->more_events = more_events; + evd->env_list = env_list; evd->page_widget = page; evd->status_label = status_label; evd->tv_log = tv_log; diff --git a/src/include/xfuncs.h b/src/include/xfuncs.h index 61188c81..5f2504b6 100644 --- a/src/include/xfuncs.h +++ b/src/include/xfuncs.h @@ -74,6 +74,19 @@ char* xasprintf(const char *format, ...); #define xsetenv abrt_xsetenv void xsetenv(const char *key, const char *value); +/* + * Utility function to unsetenv a string which was possibly putenv'ed. + * The problem here is that "natural" optimization: + * strchrnul(var_val, '=')[0] = '\0'; + * unsetenv(var_val); + * is BUGGY: if string was put into environment via putenv, + * its modification (s/=/NUL/) is illegal, and unsetenv will fail to unset it. + * Of course, saving/restoring the char wouldn't work either. + * This helper creates a copy up to '=', unsetenv's it, and frees: + */ +#define safe_unsetenv abrt_safe_unsetenv +void safe_unsetenv(const char *var_val); + #define xsocket abrt_xsocket int xsocket(int domain, int type, int protocol); #define xbind abrt_xbind diff --git a/src/lib/xfuncs.c b/src/lib/xfuncs.c index f451693a..3766d231 100644 --- a/src/lib/xfuncs.c +++ b/src/lib/xfuncs.c @@ -215,6 +215,20 @@ void xsetenv(const char *key, const char *value) die_out_of_memory(); } +void safe_unsetenv(const char *var_val) +{ + //char *name = xstrndup(var_val, strchrnul(var_val, '=') - var_val); + //unsetenv(name); + //free(name); + + /* Avoid malloc/free (name is usually very short) */ + unsigned len = strchrnul(var_val, '=') - var_val; + char name[len + 1]; + memcpy(name, var_val, len); + name[len] = '\0'; + unsetenv(name); +} + // Die with an error message if we can't open a new socket. int xsocket(int domain, int type, int protocol) { -- cgit From 077b157218254437185b5cb9d0267df72a918b79 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 7 Mar 2011 21:58:08 +0100 Subject: Fixes for g_event_config_list == NULL Signed-off-by: Denys Vlasenko --- src/gui-wizard-gtk/wizard.c | 28 ++++++++++++++++------------ src/lib/event_config.c | 14 ++++++++++---- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c index 1df70625..c7683533 100644 --- a/src/gui-wizard-gtk/wizard.c +++ b/src/gui-wizard-gtk/wizard.c @@ -484,23 +484,27 @@ static GList *export_event_config(const char *event_name) { GList *env_list = NULL; - GHashTableIter iter; - char *name; - event_config_t *cfg; - g_hash_table_iter_init(&iter, g_event_config_list); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&cfg)) + if (g_event_config_list) { - if (strcmp(cfg->name, event_name) != 0) - continue; - for (GList *lopt = cfg->options; lopt; lopt = lopt->next) + GHashTableIter iter; + char *name; + event_config_t *cfg; + g_hash_table_iter_init(&iter, g_event_config_list); + while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&cfg)) { - event_option_t *opt = lopt->data; - char *var_val = xasprintf("%s=%s", opt->name, opt->value); + if (strcmp(cfg->name, event_name) != 0) + continue; + for (GList *lopt = cfg->options; lopt; lopt = lopt->next) + { + event_option_t *opt = lopt->data; + char *var_val = xasprintf("%s=%s", opt->name, opt->value); VERB3 log("Exporting '%s'", var_val); - env_list = g_list_prepend(env_list, var_val); - putenv(var_val); + env_list = g_list_prepend(env_list, var_val); + putenv(var_val); + } } } + return env_list; } diff --git a/src/lib/event_config.c b/src/lib/event_config.c index 77cbaf4b..3eebb197 100644 --- a/src/lib/event_config.c +++ b/src/lib/event_config.c @@ -5,6 +5,7 @@ GHashTable *g_event_config_list; // (Re)loads data from /etc/abrt/events/*.{conf,xml} void load_event_config_data(void) { + free_event_config_data(); /* for each xml file call load_event_description_from_file */ /* for each conf file call load_even_options_value_from_file? * - we don't have this @@ -12,15 +13,20 @@ void load_event_config_data(void) * - or should this one be called first? */ } + /* Frees all loaded data */ void free_event_config_data(void) { - + if (g_event_config_list) + { + g_hash_table_destroy(g_event_config_list); + g_event_config_list = NULL; + } } event_config_t *get_event_config(const char *name) { - //could g_event_config_list be null? - gpointer event_config = g_hash_table_lookup(g_event_config_list, name); - return event_config; + if (!g_event_config_list) + return NULL; + return g_hash_table_lookup(g_event_config_list, name); } -- cgit From abb11fca1bcd7932d14c911d63fb7c6c347dcbcd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Mar 2011 14:07:33 +0100 Subject: make fork_execv_on_steroids capable of setting env vars too Before, it could only unset them. Signed-off-by: Denys Vlasenko --- src/daemon/Daemon.cpp | 2 +- src/include/abrtlib.h | 9 +++++++-- src/lib/run_event.c | 14 +++++++++----- src/lib/spawn.c | 12 +++++++----- src/plugins/abrt-action-analyze-c.c | 2 +- src/plugins/abrt-action-generate-backtrace.c | 11 +++++------ src/plugins/abrt-action-mailx.c | 2 +- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/daemon/Daemon.cpp b/src/daemon/Daemon.cpp index f791fb38..2d2c85ed 100644 --- a/src/daemon/Daemon.cpp +++ b/src/daemon/Daemon.cpp @@ -719,7 +719,7 @@ int main(int argc, char** argv) log_scanner_pid = fork_execv_on_steroids(EXECFLG_INPUT_NUL, (char**)scanner_argv, /*pipefds:*/ NULL, - /*unsetenv_vec:*/ NULL, + /*env_vec:*/ NULL, /*dir:*/ NULL, /*uid:*/ 0); VERB1 log("Started log scanner, pid:%d", (int)log_scanner_pid); diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h index 435c4def..f64046d9 100644 --- a/src/include/abrtlib.h +++ b/src/include/abrtlib.h @@ -170,12 +170,17 @@ enum { EXECFLG_SETGUID = 1 << 7, EXECFLG_SETSID = 1 << 8, }; -/* Returns pid */ +/* + * env_vec: list of variables to set in environment (if string has + * "VAR=VAL" form) or unset in environment (if string has no '=' char). + * + * Returns pid. + */ #define fork_execv_on_steroids abrt_fork_execv_on_steroids pid_t fork_execv_on_steroids(int flags, char **argv, int *pipefds, - char **unsetenv_vec, + char **env_vec, const char *dir, uid_t uid); /* Returns malloc'ed string. NULs are retained, and extra one is appended diff --git a/src/lib/run_event.c b/src/lib/run_event.c index a2bbc76b..3d2b3a22 100644 --- a/src/lib/run_event.c +++ b/src/lib/run_event.c @@ -245,18 +245,19 @@ int spawn_next_command(struct run_event_state *state, VERB1 log("Executing '%s'", cmd); /* Export some useful environment variables for children */ + char *env_vec[3]; /* Just exporting dump_dir_name isn't always ok: it can be "." * and some children want to cd to other directory but still * be able to find dump directory by using $DUMP_DIR... */ char *full_name = realpath(dump_dir_name, NULL); - setenv("DUMP_DIR", (full_name ? full_name : dump_dir_name), 1); + env_vec[0] = xasprintf("DUMP_DIR=%s", (full_name ? full_name : dump_dir_name)); free(full_name); - setenv("EVENT", event, 1); -//FIXME: set vars in the child, not here! Need to improve fork_execv_on_steroids... + env_vec[1] = xasprintf("EVENT=%s", event); + env_vec[2] = NULL; char *argv[4]; - argv[0] = (char*)"/bin/sh"; + argv[0] = (char*)"/bin/sh"; // TODO: honor $SHELL? argv[1] = (char*)"-c"; argv[2] = cmd; argv[3] = NULL; @@ -266,12 +267,15 @@ int spawn_next_command(struct run_event_state *state, EXECFLG_INPUT_NUL + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, argv, pipefds, - /* unsetenv_vec: */ NULL, + /* env_vec: */ env_vec, /* dir: */ dump_dir_name, /* uid(unused): */ 0 ); state->command_out_fd = pipefds[0]; + free(env_vec[0]); + free(env_vec[1]); + state->commands = g_list_remove(state->commands, cmd); return 0; diff --git a/src/lib/spawn.c b/src/lib/spawn.c index f6b7263c..188b63bd 100644 --- a/src/lib/spawn.c +++ b/src/lib/spawn.c @@ -32,7 +32,7 @@ static char *concat_str_vector(char **strings) pid_t fork_execv_on_steroids(int flags, char **argv, int *pipefds, - char **unsetenv_vec, + char **env_vec, const char *dir, uid_t uid) { @@ -69,9 +69,11 @@ pid_t fork_execv_on_steroids(int flags, xsetreuid(uid, uid); } - if (unsetenv_vec) { - while (*unsetenv_vec) - unsetenv(*unsetenv_vec++); + if (env_vec) { + /* Note: we use the glibc extension that putenv("var") + * *unsets* $var if "var" string has no '=' */ + while (*env_vec) + putenv(*env_vec++); } /* Play with stdio descriptors */ @@ -134,7 +136,7 @@ char *run_in_shell_and_save_output(int flags, const char *argv[] = { "/bin/sh", "-c", cmd, NULL }; int pipeout[2]; pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout, - /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0); + /*env_vec:*/ NULL, dir, /*uid (unused):*/ 0); size_t pos = 0; char *result = NULL; diff --git a/src/plugins/abrt-action-analyze-c.c b/src/plugins/abrt-action-analyze-c.c index 5def9aa1..635a3316 100644 --- a/src/plugins/abrt-action-analyze-c.c +++ b/src/plugins/abrt-action-analyze-c.c @@ -63,7 +63,7 @@ static char *run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec) args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, dump_dir_name); args[2] = (char*)"-n"; args[3] = NULL; - pid_t child = fork_execv_on_steroids(flags, args, pipeout, /*unsetenv_vec:*/ NULL, /*dir:*/ NULL, uid); + pid_t child = fork_execv_on_steroids(flags, args, pipeout, /*env_vec:*/ NULL, /*dir:*/ NULL, uid); free(args[1]); /* Bugs in unstrip or corrupted coredumps can cause it to enter infinite loop. diff --git a/src/plugins/abrt-action-generate-backtrace.c b/src/plugins/abrt-action-generate-backtrace.c index a8c18e36..7defc9c4 100644 --- a/src/plugins/abrt-action-generate-backtrace.c +++ b/src/plugins/abrt-action-generate-backtrace.c @@ -76,6 +76,11 @@ static char* exec_vp(char **args, uid_t uid, int redirect_stderr, int *status) "LC_MONETARY", "LC_NUMERIC", "LC_TIME", + /* Workaround for + * http://sourceware.org/bugzilla/show_bug.cgi?id=9622 + * (gdb emitting ESC sequences even with -batch) + */ + "TERM", NULL }; @@ -137,12 +142,6 @@ static char *get_backtrace(struct dump_dir *dd) char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); dd_close(dd); - // Workaround for - // http://sourceware.org/bugzilla/show_bug.cgi?id=9622 - unsetenv("TERM"); - // This is not necessary - //putenv((char*)"TERM=dumb"); - char *args[21]; args[0] = (char*)"gdb"; args[1] = (char*)"-batch"; diff --git a/src/plugins/abrt-action-mailx.c b/src/plugins/abrt-action-mailx.c index 3debf449..06f81780 100644 --- a/src/plugins/abrt-action-mailx.c +++ b/src/plugins/abrt-action-mailx.c @@ -32,7 +32,7 @@ static void exec_and_feed_input(uid_t uid, const char* text, char **args) EXECFLG_INPUT | EXECFLG_QUIET | EXECFLG_SETGUID, args, pipein, - /*unsetenv_vec:*/ NULL, + /*env_vec:*/ NULL, /*dir:*/ NULL, uid); -- cgit From 00bd0d83d1907c4a8beaae1d76fa284c0faf13bf Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Tue, 8 Mar 2011 14:13:29 +0100 Subject: add Bugzilla.xml event description --- abrt.spec | 1 + configure.ac | 2 ++ src/plugins/Bugzilla.xml | 29 +++++++++++++++++++++++++++++ src/plugins/Makefile.am | 5 +++++ 4 files changed, 37 insertions(+) create mode 100644 src/plugins/Bugzilla.xml diff --git a/abrt.spec b/abrt.spec index 6492e14a..8befece8 100644 --- a/abrt.spec +++ b/abrt.spec @@ -496,6 +496,7 @@ fi %files plugin-bugzilla %defattr(-,root,root,-) %config(noreplace) %{_sysconfdir}/%{name}/plugins/Bugzilla.conf +%{_sysconfdir}/%{name}/events/Bugzilla.xml %{_libdir}/%{name}/Bugzilla.glade %{_mandir}/man7/abrt-Bugzilla.7.gz %{_bindir}/abrt-action-bugzilla diff --git a/configure.ac b/configure.ac index bf10138d..3ced9e48 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,7 @@ AC_CHECK_HEADER([sys/inotify.h], [], CONF_DIR='${sysconfdir}/${PACKAGE_NAME}' VAR_RUN='${localstatedir}/run' PLUGINS_CONF_DIR='${sysconfdir}/${PACKAGE_NAME}/plugins' +EVENTS_DIR='${sysconfdir}/${PACKAGE_NAME}/events' EVENTS_CONF_DIR='${sysconfdir}/${PACKAGE_NAME}/events.d' PLUGINS_LIB_DIR='${libdir}/${PACKAGE_NAME}' ENABLE_SOCKET_OR_DBUS='-DENABLE_DBUS=1' @@ -104,6 +105,7 @@ AC_SUBST(CONF_DIR) AC_SUBST(VAR_RUN) AC_SUBST(PLUGINS_CONF_DIR) AC_SUBST(EVENTS_CONF_DIR) +AC_SUBST(EVENTS_DIR) AC_SUBST(PLUGINS_LIB_DIR) AC_SUBST(DEBUG_DUMPS_DIR) AC_SUBST(DEBUG_INFO_DIR) diff --git a/src/plugins/Bugzilla.xml b/src/plugins/Bugzilla.xml new file mode 100644 index 00000000..b8bd6e7a --- /dev/null +++ b/src/plugins/Bugzilla.xml @@ -0,0 +1,29 @@ + + + Bugzilla + _Report this problem to the Red Hat bug tracker + + + + + + + + diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 59e0f1a4..0a409463 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -38,6 +38,11 @@ dist_pluginsconf_DATA = \ RHTSupport.conf \ Upload.conf +eventsdir = $(EVENTS_DIR) + +dist_events_DATA = \ + Bugzilla.xml + eventsconfdir = $(EVENTS_CONF_DIR) dist_eventsconf_DATA = \ -- cgit From 02ba31ab300c06461d444f53139dd3712700abf5 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Tue, 8 Mar 2011 14:13:51 +0100 Subject: silence the output --- src/lib/event_xml_parser.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index 7b9edc4f..ee22102e 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -2,6 +2,7 @@ #include #include #include +#include "abrtlib.h" #include "event_config.h" #define EVENT_ELEMENT "event" @@ -42,12 +43,13 @@ void start_element(GMarkupParseContext *context, in_option = 1; event_option_t *option = (event_option_t *)malloc(sizeof(event_option_t)); //we need to prepend, so ui->options always points to the last created option + VERB2 log("adding option\n"); ui->options = g_list_prepend(ui->options, option); int i; for(i = 0; attribute_names[i] != NULL; ++i) { - //g_print("attr: %s:%s\n", attribute_names[i], attribute_values[i]); + VERB2 log("attr: %s:%s\n", attribute_names[i], attribute_values[i]); if(strcmp(attribute_names[i], "name") == 0) option->name = strdup(attribute_values[i]); if(strcmp(attribute_names[i], "type") == 0) @@ -107,12 +109,12 @@ void text(GMarkupParseContext *context, event_option_t *option = (event_option_t *)((ui->options)->data); if(strcmp(inner_element, LABEL_ELEMENT) == 0) { - //g_print("\tnew label: \t\t%s\n", _text); + VERB2 log("\tnew label: \t\t%s\n", _text); option->label = _text; } if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) { - //g_print("\ttooltip: \t\t%s\n", _text); + VERB2 log("\ttooltip: \t\t%s\n", _text); option->description = _text; } } @@ -144,7 +146,7 @@ void passthrough(GMarkupParseContext *context, gpointer user_data, GError **error) { - g_print("passthrough\n"); + VERB2 log("passthrough\n"); } // Called on error, including one set by other -- cgit From f6ac33ecf6635bbb34e2da196f0cab6f92724907 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Tue, 8 Mar 2011 14:52:25 +0100 Subject: event_xml_parser: minor fixes based on review from Denys --- src/lib/event_xml_parser.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index ee22102e..6f23cfb3 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -15,7 +15,7 @@ int in_option = 0; -static const char *option_types[] = +static const char *const option_types[] = { "text", "bool", @@ -25,7 +25,7 @@ static const char *option_types[] = }; // Called for open tags -void start_element(GMarkupParseContext *context, +static void start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, @@ -43,7 +43,7 @@ void start_element(GMarkupParseContext *context, in_option = 1; event_option_t *option = (event_option_t *)malloc(sizeof(event_option_t)); //we need to prepend, so ui->options always points to the last created option - VERB2 log("adding option\n"); + VERB2 log("adding option"); ui->options = g_list_prepend(ui->options, option); int i; @@ -66,14 +66,13 @@ void start_element(GMarkupParseContext *context, else { g_print("error, option nested in option!\n"); - exit(-127); } } } // Called for close tags -void end_element(GMarkupParseContext *context, +static void end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) @@ -93,7 +92,7 @@ void end_element(GMarkupParseContext *context, // Called for character data // text is not nul-terminated -void text(GMarkupParseContext *context, +static void text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, @@ -109,12 +108,12 @@ void text(GMarkupParseContext *context, event_option_t *option = (event_option_t *)((ui->options)->data); if(strcmp(inner_element, LABEL_ELEMENT) == 0) { - VERB2 log("\tnew label: \t\t%s\n", _text); + VERB2 log("\tnew label: \t\t%s", _text); option->label = _text; } if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) { - VERB2 log("\ttooltip: \t\t%s\n", _text); + VERB2 log("\ttooltip: \t\t%s", _text); option->description = _text; } } @@ -123,12 +122,12 @@ void text(GMarkupParseContext *context, /* we're not in option, so the description is for the event */ if(strcmp(inner_element, ACTION_ELEMENT) == 0) { - //g_print("\taction description: \t%s\n", _text); + VERB2 log("\taction description: \t%s", _text); ui->action = _text; } if(strcmp(inner_element, NAME_ELEMENT) == 0) { - //g_print("\tevent name: \t\t%s\n", _text); + VERB2 log("\tevent name: \t\t%s", _text); ui->name = _text; } } @@ -140,18 +139,18 @@ void text(GMarkupParseContext *context, // position, but are not otherwise interpretable. At the moment // this includes comments and processing instructions. // text is not nul-terminated -void passthrough(GMarkupParseContext *context, +static void passthrough(GMarkupParseContext *context, const gchar *passthrough_text, gsize text_len, gpointer user_data, GError **error) { - VERB2 log("passthrough\n"); + VERB2 log("passthrough"); } // Called on error, including one set by other // methods in the vtable. The GError should not be freed. -void error(GMarkupParseContext *context, +static void error(GMarkupParseContext *context, GError *error, gpointer user_data) { @@ -178,11 +177,11 @@ void load_event_description_from_file(event_config_t *event_config, const char* event_config, NULL); FILE* fin = fopen(filename, "r"); size_t read_bytes = 0; - char buff[1024] = {'\0'}; + char buff[1024]; while((read_bytes = fread(buff, 1, 1024, fin))) { g_markup_parse_context_parse(context, buff, read_bytes, NULL); } fclose(fin); - free(context); + g_markup_parse_context_free(context); } -- cgit From a6ee8958dbe6f45f95fca4fa2ea1490c7035be65 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Mar 2011 16:23:31 +0100 Subject: implement load_event_config_data. Untested. Signed-off-by: Denys Vlasenko --- src/gui-gtk/event_config_dialog.c | 14 +++--- src/hooks/Makefile.am | 1 + src/hooks/abrt-hook-ccpp.c | 2 +- src/include/report/event_config.h | 7 +++ src/lib/Makefile.am | 13 ++++-- src/lib/event_config.c | 82 +++++++++++++++++++++++++++++--- src/lib/event_xml_parser.c | 98 +++++++++++++++++++++------------------ 7 files changed, 153 insertions(+), 64 deletions(-) diff --git a/src/gui-gtk/event_config_dialog.c b/src/gui-gtk/event_config_dialog.c index 36f311c8..1da458d3 100644 --- a/src/gui-gtk/event_config_dialog.c +++ b/src/gui-gtk/event_config_dialog.c @@ -84,11 +84,11 @@ void print_option(gpointer data, gpointer user_data) void show_event_config_dialog(const char* event_name) { - event_config_t ui; - ui.options = NULL; - load_event_description_from_file(&ui, "Bugzilla.xml"); + event_config_t *ui = new_event_config(); + load_event_description_from_file(ui, "Bugzilla.xml"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( - ui.name, + ui->name, NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, @@ -96,10 +96,12 @@ void show_event_config_dialog(const char* event_name) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); - int length = g_list_length(ui.options); + int length = g_list_length(ui->options); //g_print("%i\n", length); option_table = gtk_table_new(length, 2, 0); - g_list_foreach(ui.options, &print_option, NULL); + g_list_foreach(ui->options, &print_option, NULL); + free_event_config(ui); + GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_box_pack_start(GTK_BOX(content), option_table, 0, 0, 10); gtk_widget_show_all(option_table); diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am index 6ebf3628..8d7cec50 100644 --- a/src/hooks/Makefile.am +++ b/src/hooks/Makefile.am @@ -9,6 +9,7 @@ abrt_hook_ccpp_CPPFLAGS = \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ $(GLIB_CFLAGS) \ -Wall \ -D_GNU_SOURCE diff --git a/src/hooks/abrt-hook-ccpp.c b/src/hooks/abrt-hook-ccpp.c index 46d96c91..7f2d9f55 100644 --- a/src/hooks/abrt-hook-ccpp.c +++ b/src/hooks/abrt-hook-ccpp.c @@ -380,7 +380,7 @@ int main(int argc, char** argv) unsigned setting_MaxCrashReportsSize = 0; bool setting_MakeCompatCore = false; bool setting_SaveBinaryImage = false; - parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore, &setting_SaveBinaryImage); + parse_conf(PLUGINS_CONF_DIR"/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore, &setting_SaveBinaryImage); if (!setting_SaveBinaryImage && src_fd_binary >= 0) { close(src_fd_binary); diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h index c383bce4..d2624e60 100644 --- a/src/include/report/event_config.h +++ b/src/include/report/event_config.h @@ -52,6 +52,9 @@ typedef struct int required; } event_option_t; +event_option_t *new_event_option(void); +void free_event_option(event_option_t *p); + //structure to hold the option data typedef struct { @@ -61,6 +64,10 @@ typedef struct GList *options; } event_config_t; +event_config_t *new_event_config(void); +void free_event_config(event_config_t *p); + + void load_event_description_from_file(event_config_t *event_config, const char* filename); // (Re)loads data from /etc/abrt/events/*.{conf,xml} diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 4f800a0e..863a0448 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -49,12 +49,13 @@ libreport_la_SOURCES = \ libreport_la_CPPFLAGS = \ -Wall -Werror \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ + -DLOCALSTATEDIR='"$(localstatedir)"' \ + -DVAR_RUN=\"$(VAR_RUN)\" \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DLOCALSTATEDIR='"$(localstatedir)"' \ -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ + -DEVENTS_DIR=\"$(EVENTS_DIR)\" \ $(GLIB_CFLAGS) \ -D_GNU_SOURCE libreport_la_LDFLAGS = \ @@ -66,11 +67,13 @@ libabrt_dbus_la_SOURCES = \ abrt_dbus.c abrt_dbus.h libabrt_dbus_la_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ + -DLOCALSTATEDIR='"$(localstatedir)"' \ + -DVAR_RUN=\"$(VAR_RUN)\" \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ + -DEVENTS_DIR=\"$(EVENTS_DIR)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ -Wall -Werror \ @@ -87,11 +90,13 @@ libabrt_web_la_SOURCES = \ libabrt_web_la_CPPFLAGS = \ -Wall -Werror \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ + -DLOCALSTATEDIR='"$(localstatedir)"' \ + -DVAR_RUN=\"$(VAR_RUN)\" \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ + -DEVENTS_DIR=\"$(EVENTS_DIR)\" \ $(GLIB_CFLAGS) \ $(CURL_CFLAGS) \ $(LIBXML_CFLAGS) \ diff --git a/src/lib/event_config.c b/src/lib/event_config.c index 3eebb197..18019178 100644 --- a/src/lib/event_config.c +++ b/src/lib/event_config.c @@ -1,17 +1,85 @@ -#include "event_config.h" +#include "abrtlib.h" GHashTable *g_event_config_list; +event_option_t *new_event_option(void) +{ + return xzalloc(sizeof(event_option_t)); +} + +event_config_t *new_event_config(void) +{ + return xzalloc(sizeof(event_config_t)); +} + +void free_event_option(event_option_t *p) +{ + if (!p) + return; + free(p->name); + free(p->value); + free(p->label); + free(p->description); + free(p->allowed_value); + free(p); +} + +void free_event_config(event_config_t *p) +{ + if (!p) + return; + free(p->name); + free(p->title); + free(p->action); + for (GList *opt = p->options; opt; opt = opt->next) + free_event_option(opt->data); + g_list_free(p->options); + free(p); +} + + // (Re)loads data from /etc/abrt/events/*.{conf,xml} void load_event_config_data(void) { free_event_config_data(); - /* for each xml file call load_event_description_from_file */ - /* for each conf file call load_even_options_value_from_file? - * - we don't have this - * - should re-use the event_config structure created when parsing xml - if exists - * - or should this one be called first? - */ + + DIR *dir = opendir(EVENTS_DIR); + if (!dir) + return; + + if (!g_event_config_list) + g_event_config_list = g_hash_table_new_full( + /*hash_func*/ g_str_hash, + /*key_equal_func:*/ g_str_equal, + /*key_destroy_func:*/ free, + /*value_destroy_func:*/ (GDestroyNotify) free_event_config + ); + + struct dirent *dent; + while ((dent = readdir(dir)) != NULL) + { + char *ext = strrchr(dent->d_name, '.'); + if (!ext) + continue; + ext++; + bool conf = strcmp(ext, "conf") == 0; + bool xml = strcmp(ext, "xml") == 0; + if (!conf && !xml) + continue; + + event_config_t *event_config = new_event_config(); + + char *fullname = concat_path_file(EVENTS_DIR, dent->d_name); + if (xml) + load_event_description_from_file(event_config, fullname); +// if (conf) +// load_event_values_from_file(event_config, fullname); + + free(fullname); + + *ext = '\0'; + g_hash_table_replace(g_event_config_list, xstrdup(dent->d_name), event_config); + } } /* Frees all loaded data */ diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index 6f23cfb3..5126022e 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -1,7 +1,3 @@ -//#include -#include -#include -#include #include "abrtlib.h" #include "event_config.h" @@ -13,7 +9,7 @@ #define ACTION_ELEMENT "action" #define NAME_ELEMENT "name" -int in_option = 0; +static int in_option = 0; //FIXME static const char *const option_types[] = { @@ -34,30 +30,33 @@ static void start_element(GMarkupParseContext *context, { //g_print("start: %s\n", element_name); - event_config_t *ui = (event_config_t *)user_data; + event_config_t *ui = user_data; - if(strcmp(element_name, OPTION_ELEMENT) == 0) + if (strcmp(element_name, OPTION_ELEMENT) == 0) { - if(in_option == 0) + if (in_option == 0) { in_option = 1; - event_option_t *option = (event_option_t *)malloc(sizeof(event_option_t)); + event_option_t *option = xzalloc(sizeof(*option)); //we need to prepend, so ui->options always points to the last created option VERB2 log("adding option"); ui->options = g_list_prepend(ui->options, option); int i; - for(i = 0; attribute_names[i] != NULL; ++i) + for (i = 0; attribute_names[i] != NULL; ++i) { - VERB2 log("attr: %s:%s\n", attribute_names[i], attribute_values[i]); - if(strcmp(attribute_names[i], "name") == 0) - option->name = strdup(attribute_values[i]); - if(strcmp(attribute_names[i], "type") == 0) + VERB2 log("attr: %s:%s", attribute_names[i], attribute_values[i]); + if (strcmp(attribute_names[i], "name") == 0) { - option_type_t type = 0; - for(type = OPTION_TYPE_TEXT; type < OPTION_TYPE_INVALID; ++type) + free(option->name); + option->name = xstrdup(attribute_values[i]); + } + else if (strcmp(attribute_names[i], "type") == 0) + { + option_type_t type; + for (type = OPTION_TYPE_TEXT; type < OPTION_TYPE_INVALID; ++type) { - if(strcmp(option_types[type], attribute_values[i]) == 0) + if (strcmp(option_types[type], attribute_values[i]) == 0) option->type = type; } } @@ -65,74 +64,79 @@ static void start_element(GMarkupParseContext *context, } else { - g_print("error, option nested in option!\n"); + error_msg("error, option nested in option"); } } } - // Called for close tags +// Called for close tags static void end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { - event_config_t *ui = (event_config_t *)user_data; - if(strcmp(element_name, OPTION_ELEMENT) == 0) + event_config_t *ui = user_data; + if (strcmp(element_name, OPTION_ELEMENT) == 0) { in_option = 0; } - if(strcmp(element_name, EVENT_ELEMENT) == 0) + if (strcmp(element_name, EVENT_ELEMENT) == 0) { - //we need to revers the list, because we we're prepending + //we need to reverse the list, because we we're prepending ui->options = g_list_reverse(ui->options); in_option = 0; } } - // Called for character data - // text is not nul-terminated +// Called for character data +// text is not nul-terminated static void text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { - event_config_t *ui = (event_config_t *)user_data; + event_config_t *ui = user_data; const gchar * inner_element = g_markup_parse_context_get_element(context); - char *_text = (char *)malloc(text_len+1); - strncpy(_text, text, text_len); - _text[text_len] = '\0'; - if(in_option == 1) + char *_text = xstrndup(text, text_len); + if (in_option == 1) { - event_option_t *option = (event_option_t *)((ui->options)->data); - if(strcmp(inner_element, LABEL_ELEMENT) == 0) + event_option_t *option = ui->options->data; + if (strcmp(inner_element, LABEL_ELEMENT) == 0) { - VERB2 log("\tnew label: \t\t%s", _text); + VERB2 log("new label:'%s'", _text); + free(option->label); option->label = _text; + return; } - if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) + if (strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) { - VERB2 log("\ttooltip: \t\t%s", _text); + VERB2 log("tooltip:'%s'", _text); + free(option->description); option->description = _text; + return; } } else { /* we're not in option, so the description is for the event */ - if(strcmp(inner_element, ACTION_ELEMENT) == 0) + if (strcmp(inner_element, ACTION_ELEMENT) == 0) { - VERB2 log("\taction description: \t%s", _text); + VERB2 log("action description:'%s'", _text); + free(ui->action); ui->action = _text; + return; } - if(strcmp(inner_element, NAME_ELEMENT) == 0) + if (strcmp(inner_element, NAME_ELEMENT) == 0) { - VERB2 log("\tevent name: \t\t%s", _text); + VERB2 log("event name:'%s'", _text); + free(ui->name); ui->name = _text; + return; } } - //will be freed when the event_option is freed - //free(_text); + free(_text); } // Called for strings that should be re-saved verbatim in this same @@ -154,12 +158,12 @@ static void error(GMarkupParseContext *context, GError *error, gpointer user_data) { - g_print("error\n"); + error_msg("error in XML parsing"); } /* this function takes 2 parameters - * ui -> pointer to event_config_t - * filename -> filename to read + * ui -> pointer to event_config_t + * filename -> filename to read * event_config_t contains list of options, which is malloced by hits function * and must be freed by the caller */ @@ -174,14 +178,16 @@ void load_event_description_from_file(event_config_t *event_config, const char* parser.error = &error; GMarkupParseContext *context = g_markup_parse_context_new( &parser, G_MARKUP_TREAT_CDATA_AS_TEXT, - event_config, NULL); + event_config, /*GDestroyNotify:*/ NULL); + FILE* fin = fopen(filename, "r"); size_t read_bytes = 0; char buff[1024]; - while((read_bytes = fread(buff, 1, 1024, fin))) + while ((read_bytes = fread(buff, 1, 1024, fin))) { g_markup_parse_context_parse(context, buff, read_bytes, NULL); } fclose(fin); + g_markup_parse_context_free(context); } -- cgit From e2fdf6c58eba440770624d13e25a63c3d77040db Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Tue, 8 Mar 2011 21:31:45 +0100 Subject: added event description support into xml parser - so event now has: action: description of what will happen when this event is used - the main purpose is for the event selector in wizard description: description of the event --- src/include/report/event_config.h | 1 + src/lib/event_config.c | 6 ++++-- src/lib/event_xml_parser.c | 20 ++++++++++++++------ src/plugins/Bugzilla.xml | 3 ++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h index d2624e60..e2310885 100644 --- a/src/include/report/event_config.h +++ b/src/include/report/event_config.h @@ -61,6 +61,7 @@ typedef struct char *name; //name of the event "Bugzilla" "RedHat Support Uploader" char *title; //window title - not used right now, maybe the "name" is enough? char *action;//action description to show in gui like: Upload report to the Red Hat bugzilla" + char *description; GList *options; } event_config_t; diff --git a/src/lib/event_config.c b/src/lib/event_config.c index 18019178..30335b84 100644 --- a/src/lib/event_config.c +++ b/src/lib/event_config.c @@ -31,6 +31,7 @@ void free_event_config(event_config_t *p) free(p->name); free(p->title); free(p->action); + free(p->description); for (GList *opt = p->options; opt; opt = opt->next) free_event_option(opt->data); g_list_free(p->options); @@ -42,7 +43,6 @@ void free_event_config(event_config_t *p) void load_event_config_data(void) { free_event_config_data(); - DIR *dir = opendir(EVENTS_DIR); if (!dir) return; @@ -72,12 +72,14 @@ void load_event_config_data(void) char *fullname = concat_path_file(EVENTS_DIR, dent->d_name); if (xml) load_event_description_from_file(event_config, fullname); + // if (conf) // load_event_values_from_file(event_config, fullname); free(fullname); - *ext = '\0'; + //we did ext++ so we need ext-- to point to '.' + *(--ext) = '\0'; g_hash_table_replace(g_event_config_list, xstrdup(dent->d_name), event_config); } } diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index 5126022e..a0e6c3c4 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -135,8 +135,13 @@ static void text(GMarkupParseContext *context, ui->name = _text; return; } + if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) + { + VERB2 log("event description:'%s'", _text); + free(ui->description); + ui->description = _text; + } } - free(_text); } // Called for strings that should be re-saved verbatim in this same @@ -181,13 +186,16 @@ void load_event_description_from_file(event_config_t *event_config, const char* event_config, /*GDestroyNotify:*/ NULL); FILE* fin = fopen(filename, "r"); - size_t read_bytes = 0; - char buff[1024]; - while ((read_bytes = fread(buff, 1, 1024, fin))) + if(fin != NULL) { - g_markup_parse_context_parse(context, buff, read_bytes, NULL); + size_t read_bytes = 0; + char buff[1024]; + while ((read_bytes = fread(buff, 1, 1024, fin))) + { + g_markup_parse_context_parse(context, buff, read_bytes, NULL); + } + fclose(fin); } - fclose(fin); g_markup_parse_context_free(context); } diff --git a/src/plugins/Bugzilla.xml b/src/plugins/Bugzilla.xml index b8bd6e7a..bc8e8ecb 100644 --- a/src/plugins/Bugzilla.xml +++ b/src/plugins/Bugzilla.xml @@ -1,7 +1,8 @@ Bugzilla - _Report this problem to the Red Hat bug tracker + Report this problem to the Red Hat bug tracker + Reports selected problems to the Red Hat bug tracker