Пример #1
0
void problem_data_reload_from_dump_dir(void)
{
    free(g_events);

    struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY);
    if (!dd)
        xfunc_die(); /* dd_opendir already logged error msg */

    problem_data_t *new_cd = create_problem_data_from_dump_dir(dd);
    problem_data_add_text_noteditable(new_cd, CD_DUMPDIR, g_dump_dir_name);

    g_events = list_possible_events(dd, NULL, "");
    dd_close(dd);

    /* Copy "selected for reporting" flags */
    GHashTableIter iter;
    char *name;
    struct problem_item *new_item;
    g_hash_table_iter_init(&iter, new_cd);
    while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&new_item))
    {
        struct problem_item *old_item = g_cd ? problem_data_get_item_or_NULL(g_cd, name) : NULL;
        if (old_item)
        {
            new_item->selected_by_user = old_item->selected_by_user;
            new_item->allowed_by_reporter = old_item->allowed_by_reporter;
            new_item->default_by_reporter = old_item->default_by_reporter;
            new_item->required_by_reporter = old_item->required_by_reporter;
        }
        else
        {
            new_item->selected_by_user = 0;
            new_item->allowed_by_reporter = 0;
            new_item->default_by_reporter = 0;
            new_item->required_by_reporter = 0;
        }
        //log("%s: was ->selected_by_user=%d", __func__, new_item->selected_by_user);
    }
    problem_data_free(g_cd);
    g_cd = new_cd;
}
Пример #2
0
static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings)
{
    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        xfunc_die(); /* dd_opendir already emitted error msg */
    problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
    dd_close(dd);

    const char *env;
    const char *login;
    const char *password;
    const char *bugzilla_xmlrpc;
    const char *bugzilla_url;
    bool ssl_verify;

    env = getenv("Bugzilla_Login");
    login = env ? env : get_map_string_item_or_empty(settings, "Login");
    env = getenv("Bugzilla_Password");
    password = env ? env : get_map_string_item_or_empty(settings, "Password");
    if (!login[0] || !password[0])
        error_msg_and_die(_("Empty login or password, please check your configuration"));

    env = getenv("Bugzilla_BugzillaURL");
    bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL");
    if (!bugzilla_url[0])
        bugzilla_url = "https://bugzilla.redhat.com";
    bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);

    env = getenv("Bugzilla_SSLVerify");
    ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));

    const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT);
    const char *duphash   = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH);
    if (!duphash)
        error_msg_and_die(_("Essential file '%s' is missing, can't continue.."),
                          FILENAME_DUPHASH);

    if (!*duphash)
        error_msg_and_die(_("Essential file '%s' is empty, can't continue.."),
                          FILENAME_DUPHASH);

    const char *release   = get_problem_item_content_or_NULL(problem_data, FILENAME_OS_RELEASE);
    if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */
        release = get_problem_item_content_or_NULL(problem_data, "release");

    struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify);

    log(_("Logging into Bugzilla at %s"), bugzilla_url);
    rhbz_login(client, login, password);

    log(_("Checking for duplicates"));
    char *product = NULL;
    char *version = NULL;
    parse_release_for_bz(release, &product, &version);
    free(version);

    xmlrpc_value *result;
    if (strcmp(product, "Fedora") == 0)
        result  = rhbz_search_duphash(client, component, product, duphash);
    else
        result  = rhbz_search_duphash(client, component, NULL, duphash);

    xmlrpc_value *all_bugs = rhbz_get_member("bugs", result);
    xmlrpc_DECREF(result);

    if (!all_bugs)
        error_msg_and_die(_("Missing mandatory member 'bugs'"));

    int all_bugs_size = rhbz_array_size(all_bugs);
    // When someone clones bug it has same duphash, so we can find more than 1.
    // Need to be checked if component is same.
    VERB3 log("Bugzilla has %i reports with same duphash '%s'",
              all_bugs_size, duphash);

    int bug_id = -1, dependent_bug = -1;
    struct bug_info *bz = NULL;
    if (all_bugs_size > 0)
    {
        bug_id = rhbz_bug_id(all_bugs);
        xmlrpc_DECREF(all_bugs);
        bz = rhbz_bug_info(client, bug_id);

        if (strcmp(bz->bi_product, product) != 0)
        {
            dependent_bug = bug_id;
            /* found something, but its a different product */
            free_bug_info(bz);

            xmlrpc_value *result = rhbz_search_duphash(client, component,
                                                       product, duphash);
            xmlrpc_value *all_bugs = rhbz_get_member("bugs", result);
            xmlrpc_DECREF(result);

            all_bugs_size = rhbz_array_size(all_bugs);
            if (all_bugs_size > 0)
            {
                bug_id = rhbz_bug_id(all_bugs);
                bz = rhbz_bug_info(client, bug_id);
            }
            xmlrpc_DECREF(all_bugs);
        }

    }
    free(product);

    if (all_bugs_size == 0) // Create new bug
    {
        log(_("Creating a new bug"));
        bug_id = rhbz_new_bug(client, problem_data, bug_id);

        log("Adding attachments to bug %i", bug_id);
        char bug_id_str[sizeof(int)*3 + 2];
        sprintf(bug_id_str, "%i", bug_id);

        rhbz_attachments(client, bug_id_str, problem_data);

        log(_("Logging out"));
        rhbz_logout(client);

        log("Status: NEW %s/show_bug.cgi?id=%u", bugzilla_url, bug_id);
        abrt_xmlrpc_free_client(client);
        return;
    }

    // decision based on state
    log(_("Bug is already reported: %i"), bz->bi_id);
    if ((strcmp(bz->bi_status, "CLOSED") == 0)
        && (strcmp(bz->bi_resolution, "DUPLICATE") == 0))
    {
        struct bug_info *origin;
        origin = rhbz_find_origin_bug_closed_duplicate(client, bz);
        if (origin)
        {
            free_bug_info(bz);
            bz = origin;
        }
    }

    if (strcmp(bz->bi_status, "CLOSED") != 0)
    {
        if ((strcmp(bz->bi_reporter, login) != 0)
            && (!g_list_find_custom(bz->bi_cc_list, login, (GCompareFunc)g_strcmp0)))
        {
            log(_("Add %s to CC list"), login);
            rhbz_mail_to_cc(client, bz->bi_id, login);
        }

        char *dsc = make_description_comment(problem_data);
        if (dsc)
        {
            const char *package = get_problem_item_content_or_NULL(problem_data,
                                                                   FILENAME_PACKAGE);
            const char *release = get_problem_item_content_or_NULL(problem_data,
                                                                   FILENAME_OS_RELEASE);
            if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */
                release = get_problem_item_content_or_NULL(problem_data, "release");
            const char *arch = get_problem_item_content_or_NULL(problem_data,
                                                                FILENAME_ARCHITECTURE);
            const char *is_private = get_problem_item_content_or_NULL(problem_data,
                                                                      "is_private");

            char *full_dsc = xasprintf("Package: %s\n"
                                       "Architecture: %s\n"
                                       "OS Release: %s\n"
                                       "%s", package, arch, release, dsc);

            log(_("Adding new comment to bug %d"), bz->bi_id);
            free(dsc);

            int is_priv = is_private && string_to_bool(is_private);
            rhbz_add_comment(client, bz->bi_id, full_dsc, is_priv);
            free(full_dsc);
        }
    }

    log(_("Logging out"));
    rhbz_logout(client);

    log("Status: %s%s%s %s/show_bug.cgi?id=%u",
                bz->bi_status,
                bz->bi_resolution ? " " : "",
                bz->bi_resolution ? bz->bi_resolution : "",
                bugzilla_url,
                bz->bi_id);

    dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (dd)
    {
        char *msg = xasprintf("Bugzilla: URL=%s/show_bug.cgi?id=%u", bugzilla_url, bz->bi_id);
        add_reported_to(dd, msg);
        free(msg);
        dd_close(dd);
    }

    free_problem_data(problem_data);
    free_bug_info(bz);
    abrt_xmlrpc_free_client(client);
}
Пример #3
0
int main(int argc, char **argv)
{
    abrt_init(argv);
    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_g = 1 << 2,
        OPT_b = 1 << 3,
        OPT_u = 1 << 4,
        OPT_r = 1 << 5,
    };

    const char *bugs = NULL, *release = NULL, *dump_dir_path = ".";
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT__DUMP_DIR(&dump_dir_path),
        OPT_GROUP(""),
        OPT_STRING('b', "bugs", &bugs, "ID1[,ID2,...]" , _("List of bug ids")),
        OPT_STRING('u', "url", &bodhi_url, "URL", _("Specify a bodhi server url")),
        OPT_OPTSTRING('r', "release", &release, "RELEASE", _("Specify a release")),
        OPT_END()
    };

    const char *program_usage_string = _(
        "& [-v] [-r[RELEASE]] (-b ID1[,ID2,...] | PKG-NAME) [PKG-NAME]... \n"
        "\n"
        "Search for updates on bodhi server"
    );

    unsigned opts =  parse_opts(argc, argv, program_options, program_usage_string);

    if (!bugs && !argv[optind])
        show_usage_and_die(program_usage_string, program_options);

    struct strbuf *query = strbuf_new();
    if (bugs)
        query = strbuf_append_strf(query, "bugs=%s&", bugs);

    if (opts & OPT_r)
    {
        if (release)
        {
            query = strbuf_append_strf(query, "release=%s&", release);
        }
        else
        {
            struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
            if (!dd)
                xfunc_die();

            problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
            dd_close(dd);
            if (!problem_data)
                xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */

            char *product, *version;
            map_string_t *osinfo = new_map_string();
            problem_data_get_osinfo(problem_data, osinfo);
            parse_osinfo_for_rhts(osinfo, &product, &version);
            query = strbuf_append_strf(query, "release=f%s&", version);
            free(product);
            free(version);
            free_map_string(osinfo);
        }
    }

    if (argv[optind])
    {
        char *escaped = g_uri_escape_string(argv[optind], NULL, 0);
        query = strbuf_append_strf(query, "package=%s&", escaped);
        free(escaped);
    }

    if (query->buf[query->len - 1] == '&')
        query->buf[query->len - 1] = '\0';

    log(_("Searching for updates"));
    GHashTable *update_hash_tbl = bodhi_query_list(query->buf, release);
    strbuf_free(query);

    if (!update_hash_tbl || !g_hash_table_size(update_hash_tbl))
    {
        log(_("No updates for this package found"));
        /*if (update_hash_tbl) g_hash_table_unref(update_hash_tbl);*/
        return 0;
    }

    GHashTableIter iter;
    char *name;
    struct bodhi *b;
    struct strbuf *q = strbuf_new();
    g_hash_table_iter_init(&iter, update_hash_tbl);
    while (g_hash_table_iter_next(&iter, (void **) &name, (void **) &b))
    {
        char *installed_pkg_nvr = rpm_get_nvr_by_pkg_name(name);
        if (installed_pkg_nvr && rpmvercmp(installed_pkg_nvr, b->nvr) >= 0)
        {
            log_info("Update %s is older or same as local version %s, skipping", b->nvr, installed_pkg_nvr);
            free(installed_pkg_nvr);
            continue;
        }
        free(installed_pkg_nvr);

        strbuf_append_strf(q, " %s", b->nvr);
    }

    /*g_hash_table_unref(update_hash_tbl);*/

    if (!q->len)
    {
        /*strbuf_free(q);*/
        log(_("Local version of the package is newer than available updates"));
        return 0;
    }

    /* Message is split into text and command in order to make
     * translator's job easier
     */

    /* We suggest the command which is most likely to exist on user's system,
     * and which is familiar to the largest population of users.
     * There are other tools (pkcon et al) which might be somewhat more
     * convenient (for example, they might be usable from non-root), but they
     * might be not present on the system, may evolve or be superseded,
     * while yum is unlikely to do so.
     */
    strbuf_prepend_str(q, "yum update --enablerepo=fedora --enablerepo=updates-testing");

    char *msg = xasprintf(_("An update exists which might fix your problem. "
                "You can install it by running: %s. "
                "Do you want to continue with reporting the bug?"),
                q->buf
    );
    /*strbuf_free(q);*/

    return !ask_yes_no(msg);
}
Пример #4
0
static void create_and_send_email(
                const char *dump_dir_name,
                map_string_h *settings)
{
    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        exit(1); /* error msg is already logged by dd_opendir */

    problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
    dd_close(dd);

    char* env;
    env = getenv("Mailx_Subject");
    const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : "[abrt] full crash report");
    env = getenv("Mailx_EmailFrom");
    const char *email_from = (env ? env : get_map_string_item_or_NULL(settings, "EmailFrom") ? : "user@localhost");
    env = getenv("Mailx_EmailTo");
    const char *email_to = (env ? env : get_map_string_item_or_NULL(settings, "EmailTo") ? : "root@localhost");
    env = getenv("Mailx_SendBinaryData");
    bool send_binary_data = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SendBinaryData"));

    char **args = NULL;
    unsigned arg_size = 0;
    args = append_str_to_vector(args, &arg_size, "/bin/mailx");

    char *dsc = make_description_mailx(problem_data);

    if (send_binary_data)
    {
        GHashTableIter iter;
        char *name;
        struct problem_item *value;
        g_hash_table_iter_init(&iter, problem_data);
        while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
        {
            if (value->flags & CD_FLAG_BIN)
            {
                args = append_str_to_vector(args, &arg_size, "-a");
                args = append_str_to_vector(args, &arg_size, value->content);
            }
        }
    }

    args = append_str_to_vector(args, &arg_size, "-s");
    args = append_str_to_vector(args, &arg_size, subject);
    args = append_str_to_vector(args, &arg_size, "-r");
    args = append_str_to_vector(args, &arg_size, email_from);
    args = append_str_to_vector(args, &arg_size, email_to);

    log(_("Sending an email..."));
    exec_and_feed_input(dsc, args);

    free(dsc);

    while (*args)
        free(*args++);
    args -= arg_size;
    free(args);

    free_problem_data(problem_data);

    dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (dd)
    {
        char *msg = xasprintf("email: %s", email_to);
        add_reported_to(dd, msg);
        free(msg);
        dd_close(dd);
    }
    log("Email was sent to: %s", email_to);
}
Пример #5
0
int main(int argc, char **argv)
{
    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "\b [-v] -d DIR [-o FILE] [-a yes/no] [-r]\n"
        "\n"
        "Prints problem information to standard output or FILE"
    );
    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_o = 1 << 2,
        OPT_a = 1 << 3,
        OPT_r = 1 << 4,
    };
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_STRING('d', NULL, &dump_dir_name, "DIR"   , _("Dump directory")),
        OPT_STRING('o', NULL, &output_file  , "FILE"  , _("Output file")),
        OPT_STRING('a', NULL, &append       , "yes/no", _("Append to, or overwrite FILE")),
        OPT_BOOL(  'r', NULL, NULL          ,           _("Create reported_to in DIR")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(0);

    if (output_file)
    {
        if (string_to_bool(append))
            open_mode = "a";
        if (!freopen(output_file, open_mode, stdout))
            perror_msg_and_die("Can't open '%s'", output_file);
    }

    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        return 1; /* error message is already logged */

    problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
    dd_close(dd);

    char *dsc = make_description_logger(problem_data);
    fputs(dsc, stdout);
    if (open_mode[0] == 'a')
        fputs("\nEND:\n\n", stdout);
    free(dsc);
    free_problem_data(problem_data);

    if (output_file)
    {
        if (opts & OPT_r)
        {
            dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
            if (dd)
            {
                char *msg = xasprintf("file: %s", output_file);
                add_reported_to(dd, msg);
                free(msg);
                dd_close(dd);
            }
        }
        const char *format = (open_mode[0] == 'a' ? _("The report was appended to %s") : _("The report was stored to %s"));
        log(format, output_file);
    }

    return 0;
}