|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
Copyright (C) 2011 ABRT Team
|
|
Packit |
4f15d5 |
Copyright (C) 2011 RedHat inc.
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
4f15d5 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
4f15d5 |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
4f15d5 |
(at your option) any later version.
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
4f15d5 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4f15d5 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
4f15d5 |
GNU General Public License for more details.
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
You should have received a copy of the GNU General Public License along
|
|
Packit |
4f15d5 |
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
4f15d5 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#include "internal_libreport.h"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GHashTable *g_event_config_list;
|
|
Packit |
4f15d5 |
static GHashTable *g_event_config_symlinks;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
invalid_option_t *new_invalid_option(void)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return xzalloc(sizeof(invalid_option_t));
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_option_t *new_event_option(void)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return xzalloc(sizeof(event_option_t));
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *new_event_config(const char *name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
event_config_t *e = xzalloc(sizeof(event_config_t));
|
|
Packit |
4f15d5 |
e->info = new_config_info(name);
|
|
Packit |
4f15d5 |
return e;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
config_item_info_t *ec_get_config_info(event_config_t * ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return ec->info;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void ec_set_screen_name(event_config_t *ec, const char *screen_name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
ci_set_screen_name(ec->info, screen_name);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *ec_get_screen_name(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return ci_get_screen_name(ec->info);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *ec_get_description(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return ci_get_description(ec->info);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void ec_set_description(event_config_t *ec, const char *description)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
ci_set_description(ec->info, description);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *ec_get_name(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return ci_get_name(ec->info);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *ec_get_long_desc(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return ci_get_long_desc(ec->info);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void ec_set_long_desc(event_config_t *ec, const char *long_descr)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
ci_set_long_desc(ec->info, long_descr);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
bool ec_is_configurable(event_config_t* ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
return g_list_length(ec->options) > 0;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void ec_print(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
printf("%s\n\t%s\n\t%s\n",
|
|
Packit |
4f15d5 |
ec_get_name(ec),
|
|
Packit |
4f15d5 |
ec_get_screen_name(ec),
|
|
Packit |
4f15d5 |
ec_get_description(ec)
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
bool ec_restricted_access_enabled(event_config_t *ec)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!ec->ec_supports_restricted_access)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (ec->ec_restricted_access_option != NULL)
|
|
Packit |
4f15d5 |
log_warning("Event '%s' does not support restricted access but has the option", ec_get_name(ec));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (ec->ec_restricted_access_option == NULL)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
log_debug("Event '%s' supports restricted access but is missing the option", ec_get_name(ec));
|
|
Packit |
4f15d5 |
return false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_option_t *eo = get_event_option_from_list(ec->ec_restricted_access_option, ec->options);
|
|
Packit |
4f15d5 |
if (eo == NULL)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
log_warning("Event '%s' supports restricted access but the option is not defined", ec_get_name(ec));
|
|
Packit |
4f15d5 |
return false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (eo->eo_type != OPTION_TYPE_BOOL)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
log_warning("Restricted option '%s' of Event '%s' is not of 'bool' type",
|
|
Packit |
4f15d5 |
ec->ec_restricted_access_option, ec_get_name(ec));
|
|
Packit |
4f15d5 |
return false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return eo->eo_value != NULL && string_to_bool(eo->eo_value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void free_invalid_options(invalid_option_t *p)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!p)
|
|
Packit |
4f15d5 |
return;
|
|
Packit |
4f15d5 |
free(p->invopt_name);
|
|
Packit |
4f15d5 |
free(p->invopt_error);
|
|
Packit |
4f15d5 |
free(p);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void free_event_option(event_option_t *p)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!p)
|
|
Packit |
4f15d5 |
return;
|
|
Packit |
4f15d5 |
free(p->eo_name);
|
|
Packit |
4f15d5 |
free(p->eo_value);
|
|
Packit |
4f15d5 |
free(p->eo_label);
|
|
Packit |
4f15d5 |
free(p->eo_note_html);
|
|
Packit |
4f15d5 |
//free(p->eo_description);
|
|
Packit |
4f15d5 |
//free(p->eo_allowed_value);
|
|
Packit |
4f15d5 |
free(p);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void free_event_config(event_config_t *p)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!p)
|
|
Packit |
4f15d5 |
return;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free_config_info(p->info);
|
|
Packit |
4f15d5 |
free(p->ec_creates_items);
|
|
Packit |
4f15d5 |
free(p->ec_requires_items);
|
|
Packit |
4f15d5 |
free(p->ec_exclude_items_by_default);
|
|
Packit |
4f15d5 |
free(p->ec_include_items_by_default);
|
|
Packit |
4f15d5 |
free(p->ec_exclude_items_always);
|
|
Packit |
4f15d5 |
free(p->ec_restricted_access_option);
|
|
Packit |
4f15d5 |
g_list_free_full(p->ec_imported_event_names, free);
|
|
Packit |
4f15d5 |
g_list_free_full(p->options, (GDestroyNotify)free_event_option);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free(p);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
static int cmp_event_option_name_with_string(gconstpointer a, gconstpointer b)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
const event_option_t *evopt = a;
|
|
Packit |
4f15d5 |
return !evopt->eo_name || strcmp(evopt->eo_name, (char *)b) != 0;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_option_t *get_event_option_from_list(const char *name, GList *options)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GList *elem = g_list_find_custom(options, name, &cmp_event_option_name_with_string);
|
|
Packit |
4f15d5 |
if (elem)
|
|
Packit |
4f15d5 |
return (event_option_t *)elem->data;
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
static void load_config_files(const char *dir_path)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GList *conf_files = get_file_list(dir_path, "conf");
|
|
Packit |
4f15d5 |
while (conf_files != NULL)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
file_obj_t *file = (file_obj_t *)conf_files->data;
|
|
Packit |
4f15d5 |
char *fullpath = file->fullpath;
|
|
Packit |
4f15d5 |
char *filename = file->filename;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *event_config = get_event_config(filename);
|
|
Packit |
4f15d5 |
bool new_config = (!event_config);
|
|
Packit |
4f15d5 |
if (new_config)
|
|
Packit |
4f15d5 |
event_config = new_event_config(filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
map_string_t *keys_and_values = new_map_string();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
load_conf_file(fullpath, keys_and_values, /*skipKeysWithoutValue:*/ false);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Insert or replace every key/value from keys_and_values to event_config->option */
|
|
Packit |
4f15d5 |
map_string_iter_t iter;
|
|
Packit |
4f15d5 |
const char *name;
|
|
Packit |
4f15d5 |
const char *value;
|
|
Packit |
4f15d5 |
init_map_string_iter(&iter, keys_and_values);
|
|
Packit |
4f15d5 |
while (next_map_string_iter(&iter, &name, &value))
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
event_option_t *opt;
|
|
Packit |
4f15d5 |
GList *elem = g_list_find_custom(event_config->options, name,
|
|
Packit |
4f15d5 |
cmp_event_option_name_with_string);
|
|
Packit |
4f15d5 |
if (elem)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
opt = elem->data;
|
|
Packit |
4f15d5 |
// log_warning("conf: replacing '%s' value:'%s'->'%s'", name, opt->value, value);
|
|
Packit |
4f15d5 |
free(opt->eo_value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
// log_warning("conf: new value %s='%s'", name, value);
|
|
Packit |
4f15d5 |
opt = new_event_option();
|
|
Packit |
4f15d5 |
opt->eo_name = xstrdup(name);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
opt->eo_value = xstrdup(value);
|
|
Packit |
4f15d5 |
if (!elem)
|
|
Packit |
4f15d5 |
event_config->options = g_list_append(event_config->options, opt);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free_map_string(keys_and_values);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (new_config)
|
|
Packit |
4f15d5 |
g_hash_table_replace(g_event_config_list, xstrdup(ec_get_name(event_config)), event_config);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free_file_obj(file);
|
|
Packit |
4f15d5 |
conf_files = g_list_delete_link(conf_files, conf_files);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* (Re)loads data from /etc/abrt/events/foo.{xml,conf} and $XDG_CACHE_HOME/abrt/events/foo.conf */
|
|
Packit |
4f15d5 |
GHashTable *load_event_config_data(void)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
free_event_config_data();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (!g_event_config_list)
|
|
Packit |
4f15d5 |
g_event_config_list = g_hash_table_new_full(
|
|
Packit |
4f15d5 |
/*hash_func*/ g_str_hash,
|
|
Packit |
4f15d5 |
/*key_equal_func:*/ g_str_equal,
|
|
Packit |
4f15d5 |
/*key_destroy_func:*/ free,
|
|
Packit |
4f15d5 |
/*value_destroy_func:*/ (GDestroyNotify) free_event_config
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
if (!g_event_config_symlinks)
|
|
Packit |
4f15d5 |
g_event_config_symlinks = g_hash_table_new_full(
|
|
Packit |
4f15d5 |
/*hash_func*/ g_str_hash,
|
|
Packit |
4f15d5 |
/*key_equal_func:*/ g_str_equal,
|
|
Packit |
4f15d5 |
/*key_destroy_func:*/ free,
|
|
Packit |
4f15d5 |
/*value_destroy_func:*/ free
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GList *event_files = get_file_list(EVENTS_DIR, "xml");
|
|
Packit |
4f15d5 |
while (event_files)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
file_obj_t *file = (file_obj_t *)event_files->data;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *event_config = get_event_config(file->filename);
|
|
Packit |
4f15d5 |
bool new_config = (!event_config);
|
|
Packit |
4f15d5 |
if (new_config)
|
|
Packit |
4f15d5 |
event_config = new_event_config(file->filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
load_event_description_from_file(event_config, file->fullpath);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (new_config)
|
|
Packit |
4f15d5 |
g_hash_table_replace(g_event_config_list, xstrdup(ec_get_name(event_config)), event_config);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free_file_obj(file);
|
|
Packit |
4f15d5 |
event_files = g_list_delete_link(event_files, event_files);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* EVENTS_DIR -> /usr/share/libreport/events/$EVENT_NAME.xml
|
|
Packit |
4f15d5 |
* - event xml definition files
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* EVENTS_CONF_DIR -> /etc/libreport/events/$EVENT_NAME.conf
|
|
Packit |
4f15d5 |
* - default values for xml definitions
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* https://fedorahosted.org/abrt/wiki/AbrtConfiguration#Adjustingpluginconfiguration
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
load_config_files(EVENTS_CONF_DIR);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *cachedir;
|
|
Packit |
4f15d5 |
cachedir = concat_path_file(g_get_user_cache_dir(), "abrt/events");
|
|
Packit |
4f15d5 |
load_config_files(cachedir);
|
|
Packit |
4f15d5 |
free(cachedir);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return g_event_config_list;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Frees all loaded data */
|
|
Packit |
4f15d5 |
void free_event_config_data(void)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (g_event_config_list)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
g_hash_table_destroy(g_event_config_list);
|
|
Packit |
4f15d5 |
g_event_config_list = NULL;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
if (g_event_config_symlinks)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
g_hash_table_destroy(g_event_config_symlinks);
|
|
Packit |
4f15d5 |
g_event_config_symlinks = NULL;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *get_event_config(const char *name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!g_event_config_list)
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
if (g_event_config_symlinks)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *link = g_hash_table_lookup(g_event_config_symlinks, name);
|
|
Packit |
4f15d5 |
if (link)
|
|
Packit |
4f15d5 |
name = link;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
return g_hash_table_lookup(g_event_config_list, name);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GList *export_event_config(const char *event_name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GList *env_list = NULL;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *config = get_event_config(event_name);
|
|
Packit |
4f15d5 |
if (config)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GList *imported = config->ec_imported_event_names;
|
|
Packit |
4f15d5 |
while (imported)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GList *exported = export_event_config(/*Event name*/imported->data);
|
|
Packit |
4f15d5 |
while (exported)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!g_list_find_custom(env_list, exported->data, (GCompareFunc)strcmp))
|
|
Packit |
4f15d5 |
/* It is not necessary to make a copy of opt->eo_name */
|
|
Packit |
4f15d5 |
/* since its memory is owned by event_option_t and it */
|
|
Packit |
4f15d5 |
/* has global scope */
|
|
Packit |
4f15d5 |
env_list = g_list_prepend(env_list, exported->data);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
exported = g_list_remove_link(exported, exported);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
imported = g_list_next(imported);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GList *lopt;
|
|
Packit |
4f15d5 |
for (lopt = config->options; lopt; lopt = lopt->next)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
event_option_t *opt = lopt->data;
|
|
Packit |
4f15d5 |
if (!opt->eo_value)
|
|
Packit |
4f15d5 |
continue;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
log_debug("Exporting '%s=%s'", opt->eo_name, opt->eo_value);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Add the exported key only if it is not in the list */
|
|
Packit |
4f15d5 |
if (!g_list_find_custom(env_list, opt->eo_name, (GCompareFunc)strcmp))
|
|
Packit |
4f15d5 |
/* It is not necessary to make a copy of opt->eo_name */
|
|
Packit |
4f15d5 |
/* since its memory is owned by opt and it has global scope */
|
|
Packit |
4f15d5 |
env_list = g_list_prepend(env_list, opt->eo_name);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* setenv() makes copies of strings */
|
|
Packit |
4f15d5 |
xsetenv(opt->eo_name, opt->eo_value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return env_list;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
* Goes through given list and calls unsetnev() for each list item.
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* Accepts a list of 'const char *' type items which contains names of exported
|
|
Packit |
4f15d5 |
* environment variables and which was returned from export_event_config()
|
|
Packit |
4f15d5 |
* function.
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
void unexport_event_config(GList *env_list)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
while (env_list)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *var_val = env_list->data;
|
|
Packit |
4f15d5 |
log_debug("Unexporting '%s'", var_val);
|
|
Packit |
4f15d5 |
safe_unsetenv(var_val);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* The list doesn't own memory of values: see export_event_config() */
|
|
Packit |
4f15d5 |
env_list = g_list_remove(env_list, var_val);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* return NULL if successful otherwise appropriate error message */
|
|
Packit |
4f15d5 |
static char *validate_event_option(event_option_t *opt)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (!opt->eo_allow_empty && (!opt->eo_value || !opt->eo_value[0]))
|
|
Packit |
4f15d5 |
return xstrdup(_("Missing mandatory value"));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* if value is NULL and allow-empty yes than it doesn't make sence to check it */
|
|
Packit |
4f15d5 |
if (!opt->eo_value)
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const gchar *s = NULL;
|
|
Packit |
4f15d5 |
if (!g_utf8_validate(opt->eo_value, -1, &s))
|
|
Packit |
4f15d5 |
return xasprintf(_("Invalid utf8 character '%c'"), *s);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
switch (opt->eo_type) {
|
|
Packit |
4f15d5 |
case OPTION_TYPE_TEXT:
|
|
Packit |
4f15d5 |
case OPTION_TYPE_PASSWORD:
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
case OPTION_TYPE_NUMBER:
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *endptr;
|
|
Packit |
4f15d5 |
errno = 0;
|
|
Packit |
4f15d5 |
long r = strtol(opt->eo_value, &endptr, 10);
|
|
Packit |
4f15d5 |
(void) r;
|
|
Packit |
4f15d5 |
if (errno != 0 || endptr == opt->eo_value || *endptr != '\0')
|
|
Packit |
4f15d5 |
return xasprintf(_("Invalid number '%s'"), opt->eo_value);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
case OPTION_TYPE_BOOL:
|
|
Packit |
4f15d5 |
/* note: should match strings which string_to_bool accepts */
|
|
Packit |
4f15d5 |
if (strcasecmp(opt->eo_value, "yes") != 0
|
|
Packit |
4f15d5 |
&& strcasecmp(opt->eo_value, "no") != 0
|
|
Packit |
4f15d5 |
&& strcasecmp(opt->eo_value, "on") != 0
|
|
Packit |
4f15d5 |
&& strcasecmp(opt->eo_value, "off") != 0
|
|
Packit |
4f15d5 |
&& strcasecmp(opt->eo_value, "true") != 0
|
|
Packit |
4f15d5 |
&& strcasecmp(opt->eo_value, "false") != 0
|
|
Packit |
4f15d5 |
&& strcmp(opt->eo_value, "1") != 0
|
|
Packit |
4f15d5 |
&& strcmp(opt->eo_value, "0") != 0
|
|
Packit |
4f15d5 |
) {
|
|
Packit |
4f15d5 |
return xasprintf(_("Invalid boolean value '%s'"), opt->eo_value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
case OPTION_TYPE_HINT_HTML:
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
default:
|
|
Packit |
4f15d5 |
return xstrdup(_("Unsupported option type"));
|
|
Packit |
4f15d5 |
};
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GList *get_options_with_err_msg(const char *event_name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
INITIALIZE_LIBREPORT();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
event_config_t *config = get_event_config(event_name);
|
|
Packit |
4f15d5 |
if (!config)
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
GList *iter, *err_list = NULL;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
for (iter = config->options; iter; iter = iter->next)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
event_option_t *opt = (event_option_t *)iter->data;
|
|
Packit |
4f15d5 |
char *err = validate_event_option(opt);
|
|
Packit |
4f15d5 |
if (err)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
invalid_option_t *inv_opt = new_invalid_option();
|
|
Packit |
4f15d5 |
inv_opt->invopt_name = xstrdup(opt->eo_name);
|
|
Packit |
4f15d5 |
inv_opt->invopt_error = xstrdup(err);
|
|
Packit |
4f15d5 |
err_list = g_list_prepend(err_list, inv_opt);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free(err);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (err_list != NULL)
|
|
Packit |
4f15d5 |
return g_list_reverse(err_list);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return NULL;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
* This function checks if a value of problem's backtrace rating is acceptable
|
|
Packit |
4f15d5 |
* for event according to event's required rating value.
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* The solved problem seems to be pretty straightforward but there are some
|
|
Packit |
4f15d5 |
* pitfalls.
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* 1. Is rating acceptable if event doesn't have configuration?
|
|
Packit |
4f15d5 |
* 2. Is rating acceptable if problem's data doesn't contains rating value?
|
|
Packit |
4f15d5 |
* 3. Is rating acceptable if rating value is not a number?
|
|
Packit |
4f15d5 |
* 4. What message show to user if there is a concern about usability?
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
bool check_problem_rating_usability(const event_config_t *cfg,
|
|
Packit |
4f15d5 |
problem_data_t *pd,
|
|
Packit |
4f15d5 |
char **description,
|
|
Packit |
4f15d5 |
char **detail)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
INITIALIZE_LIBREPORT();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *tmp_desc = NULL;
|
|
Packit |
4f15d5 |
char *tmp_detail = NULL;
|
|
Packit |
4f15d5 |
bool result = true;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (!cfg)
|
|
Packit |
4f15d5 |
goto finish;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *rating_str = problem_data_get_content_or_NULL(pd, FILENAME_RATING);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (!rating_str)
|
|
Packit |
4f15d5 |
goto finish;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* just to be sure */
|
|
Packit |
4f15d5 |
result = false;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const long minimal_rating = cfg->ec_minimal_rating;
|
|
Packit |
4f15d5 |
char *endptr;
|
|
Packit |
4f15d5 |
errno = 0;
|
|
Packit |
4f15d5 |
const long rating = strtol(rating_str, &endptr, 10);
|
|
Packit |
4f15d5 |
if (errno != 0 || endptr == rating_str || *endptr != '\0')
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
tmp_desc = xasprintf(
|
|
Packit |
4f15d5 |
_("The problem cannot be reported due to an invalid data. " \
|
|
Packit |
4f15d5 |
"'%s' file does not contain a number."),
|
|
Packit |
4f15d5 |
FILENAME_RATING);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
tmp_detail = xstrdup(_("Please report this problem to ABRT project developers."));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
result = false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else if (rating == minimal_rating) /* bt is usable, but not complete, so show a warning */
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
tmp_desc = xstrdup(_("The backtrace is incomplete, please make sure you provide the steps to reproduce."));
|
|
Packit |
4f15d5 |
tmp_detail = xstrdup(_("The backtrace probably can't help developer to diagnose the bug."));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
result = true;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else if (rating < minimal_rating)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
tmp_desc = xstrdup(_("Reporting disabled because the backtrace is unusable."));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *package = problem_data_get_content_or_NULL(pd, FILENAME_PACKAGE);
|
|
Packit |
4f15d5 |
if (package && package[0])
|
|
Packit |
4f15d5 |
tmp_detail = xasprintf(_("Please try to install debuginfo manually using the command: \"debuginfo-install %s\" and try again."), package);
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
tmp_detail = xstrdup(_("A proper debuginfo is probably missing or the coredump is corrupted."));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
result = false;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else /* rating > minimal_rating */
|
|
Packit |
4f15d5 |
result = true;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
finish:
|
|
Packit |
4f15d5 |
if (description)
|
|
Packit |
4f15d5 |
*description = tmp_desc;
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
free(tmp_desc);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (detail)
|
|
Packit |
4f15d5 |
*detail = tmp_detail;
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
free(tmp_detail);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return result;
|
|
Packit |
4f15d5 |
}
|