From 373fc9da8e522132b805eab3a5d51bebc40f35ba Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Jul 21 2011 17:35:08 +0000 Subject: fixed conflict with report rhbz#723320 --- diff --git a/0001-fix-el6-keyring.patch b/0001-fix-el6-keyring.patch new file mode 100644 index 0000000..86f642e --- /dev/null +++ b/0001-fix-el6-keyring.patch @@ -0,0 +1,25 @@ +From e8408578b1d0b320e8abf27f96186e8fa1f5e4dd Mon Sep 17 00:00:00 2001 +From: Michal Toman +Date: Mon, 18 Jul 2011 16:38:02 +0200 +Subject: [PATCH 01/12] fix el6 keyring + +--- + src/gtk-helpers/event_config_dialog.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c +index 219f841..c06ba4b 100644 +--- a/src/gtk-helpers/event_config_dialog.c ++++ b/src/gtk-helpers/event_config_dialog.c +@@ -318,7 +318,7 @@ static void save_settings_to_keyring(const char *event_name) + GNOME_KEYRING_ITEM_GENERIC_SECRET, /* type */ + event_name, /* display name */ + attrs, /* attributes */ +- NULL, /* secret - no special handling for password it's stored in attrs */ ++ "", /* secret - no special handling for password it's stored in attrs */ + 1, /* update if exist */ + &item_id); + VERB2 log("created new item with id: %i", item_id); +-- +1.7.6 + diff --git a/0002-Add-a-button-to-add-more-files-to-dump-dir.-Closes-1.patch b/0002-Add-a-button-to-add-more-files-to-dump-dir.-Closes-1.patch new file mode 100644 index 0000000..e5f5ea9 --- /dev/null +++ b/0002-Add-a-button-to-add-more-files-to-dump-dir.-Closes-1.patch @@ -0,0 +1,134 @@ +From 431cad6bc413aaf296b49a510bf5e37aaffc2263 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 19 Jul 2011 10:04:35 +0200 +Subject: [PATCH 02/12] Add a button to add more files to dump dir. Closes #17 + +Signed-off-by: Denys Vlasenko +--- + src/gui-wizard-gtk/wizard.c | 49 ++++++++++++++++++++++++++++++++++++++- + src/gui-wizard-gtk/wizard.glade | 28 ++++++++++++++++++++++ + 2 files changed, 76 insertions(+), 1 deletions(-) + +diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c +index ada9823..cdc4a5c 100644 +--- a/src/gui-wizard-gtk/wizard.c ++++ b/src/gui-wizard-gtk/wizard.c +@@ -63,6 +63,7 @@ static GtkWidget *g_widget_warnings_area; + static GtkBox *g_box_warning_labels; + static GtkToggleButton *g_tb_approve_bt; + static GtkButton *g_btn_refresh; ++static GtkButton *g_btn_add_file; + + static GtkLabel *g_lbl_reporters; + static GtkLabel *g_lbl_size; +@@ -1752,6 +1753,7 @@ static void add_pages() + g_search_entry_bt = GTK_ENTRY( gtk_builder_get_object(builder, "entry_search_bt")); + g_container_details1 = GTK_CONTAINER( gtk_builder_get_object(builder, "container_details1")); + g_container_details2 = GTK_CONTAINER( gtk_builder_get_object(builder, "container_details2")); ++ g_btn_add_file = GTK_BUTTON( gtk_builder_get_object(builder, "btn_add_file")); + g_lbl_reporters = GTK_LABEL( gtk_builder_get_object(builder, "lbl_reporters")); + g_lbl_size = GTK_LABEL( gtk_builder_get_object(builder, "lbl_size")); + +@@ -1861,7 +1863,50 @@ static void save_edited_one_liner(GtkCellRendererText *renderer, + } + } + +-static void create_details_treeview() ++static void on_btn_add_file(GtkButton *button) ++{ ++ GtkWidget *dialog = gtk_file_chooser_dialog_new( ++ "Attach File", ++ GTK_WINDOW(g_assistant), ++ GTK_FILE_CHOOSER_ACTION_OPEN, ++ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, ++ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, ++ NULL ++ ); ++ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) ++ { ++ char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); ++ ++ char *basename = strrchr(filename, '/'); ++ if (!basename) /* wtf? */ ++ goto free_and_ret; ++ basename++; ++ ++ struct stat statbuf; ++ if (stat(filename, &statbuf) != 0 || !S_ISREG(statbuf.st_mode)) ++ goto free_and_ret; ++ ++ struct problem_item *item = get_problem_data_item_or_NULL(g_cd, basename); ++ if (!item || (item->flags & CD_FLAG_ISEDITABLE)) ++ { ++ char *new_name = concat_path_file(g_dump_dir_name, basename); ++ /* TODO: error check */ ++ copy_file(filename, new_name, 0666); ++ free(new_name); ++ reload_problem_data_from_dump_dir(); ++ update_gui_state_from_problem_data(); ++ } ++ else ++ { ++ /* TODO: error dialog */ ++ } ++ free_and_ret: ++ g_free(filename); ++ } ++ gtk_widget_destroy(dialog); ++} ++ ++static void create_details_treeview(void) + { + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; +@@ -1944,6 +1989,8 @@ void create_assistant(void) + g_signal_connect(g_btn_refresh, "clicked", G_CALLBACK(on_btn_refresh_clicked), NULL); + g_signal_connect(gtk_text_view_get_buffer(g_tv_comment), "changed", G_CALLBACK(on_comment_changed), NULL); + ++ g_signal_connect(g_btn_add_file, "clicked", G_CALLBACK(on_btn_add_file), NULL); ++ + /* init searching */ + GtkTextBuffer *backtrace_buf = gtk_text_view_get_buffer(g_tv_backtrace); + /* found items background */ +diff --git a/src/gui-wizard-gtk/wizard.glade b/src/gui-wizard-gtk/wizard.glade +index 49acd67..ba8b09a 100644 +--- a/src/gui-wizard-gtk/wizard.glade ++++ b/src/gui-wizard-gtk/wizard.glade +@@ -685,6 +685,34 @@ + 2 + + ++ ++ ++ True ++ False ++ ++ ++ Attach a file ++ True ++ True ++ True ++ False ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ + + + +-- +1.7.6 + diff --git a/0003-Ignore-files-which-seem-to-be-editor-backups.-Closes.patch b/0003-Ignore-files-which-seem-to-be-editor-backups.-Closes.patch new file mode 100644 index 0000000..c4068c8 --- /dev/null +++ b/0003-Ignore-files-which-seem-to-be-editor-backups.-Closes.patch @@ -0,0 +1,32 @@ +From e4cc4a2a0dfdf644613861e6bd922152a67bf3b8 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 19 Jul 2011 10:21:49 +0200 +Subject: [PATCH 03/12] Ignore files which seem to be editor backups. Closes + bz#707959 + +Signed-off-by: Denys Vlasenko +--- + src/lib/problem_data.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/src/lib/problem_data.c b/src/lib/problem_data.c +index fcaf8fa..0878b88 100644 +--- a/src/lib/problem_data.c ++++ b/src/lib/problem_data.c +@@ -309,6 +309,13 @@ void load_problem_data_from_dump_dir(problem_data_t *problem_data, struct dump_d + goto next; + } + ++ if (short_name[0] == '#' ++ || (short_name[0] && short_name[strlen(short_name) - 1] == '~') ++ ) { ++ //log("Excluded (editor backup file):'%s'", short_name); ++ goto next; ++ } ++ + ssize_t sz = 4*1024; + char *text = NULL; + bool editable = is_editable_file(short_name); +-- +1.7.6 + diff --git a/0004-wizard-steal-directory-before-copying-added-files-to.patch b/0004-wizard-steal-directory-before-copying-added-files-to.patch new file mode 100644 index 0000000..b8998ef --- /dev/null +++ b/0004-wizard-steal-directory-before-copying-added-files-to.patch @@ -0,0 +1,195 @@ +From 9e36fa04511b245ae904d67cbb9cd803d3a7e7c6 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 19 Jul 2011 12:06:01 +0200 +Subject: [PATCH 04/12] wizard: steal directory before copying added files to + it + +Signed-off-by: Denys Vlasenko +--- + src/gui-wizard-gtk/wizard.c | 163 +++++++++++++++++++++++-------------------- + 1 files changed, 86 insertions(+), 77 deletions(-) + +diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c +index cdc4a5c..847e84c 100644 +--- a/src/gui-wizard-gtk/wizard.c ++++ b/src/gui-wizard-gtk/wizard.c +@@ -1675,6 +1675,92 @@ static void search_timeout(GtkEntry *entry) + g_timeout = g_timeout_add(500, &highlight_search, (gpointer)entry); + } + ++static void save_edited_one_liner(GtkCellRendererText *renderer, ++ gchar *tree_path, ++ gchar *new_text, ++ gpointer user_data) ++{ ++ //log("path:'%s' new_text:'%s'", tree_path, new_text); ++ ++ GtkTreeIter iter; ++ if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(g_ls_details), &iter, tree_path)) ++ return; ++ gchar *item_name = NULL; ++ gtk_tree_model_get(GTK_TREE_MODEL(g_ls_details), &iter, ++ DETAIL_COLUMN_NAME, &item_name, ++ -1); ++ if (!item_name) /* paranoia, should never happen */ ++ return; ++ struct problem_item *item = get_problem_data_item_or_NULL(g_cd, item_name); ++ if (item && (item->flags & CD_FLAG_ISEDITABLE)) ++ { ++ struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); ++ dd = steal_if_needed(dd); ++ if (dd && dd->locked) ++ { ++ dd_save_text(dd, item_name, new_text); ++ free(item->content); ++ item->content = xstrdup(new_text); ++ gtk_list_store_set(g_ls_details, &iter, ++ DETAIL_COLUMN_VALUE, new_text, ++ -1); ++ } ++ dd_close(dd); ++ } ++} ++ ++static void on_btn_add_file(GtkButton *button) ++{ ++ GtkWidget *dialog = gtk_file_chooser_dialog_new( ++ "Attach File", ++ GTK_WINDOW(g_assistant), ++ GTK_FILE_CHOOSER_ACTION_OPEN, ++ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, ++ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, ++ NULL ++ ); ++ char *filename = NULL; ++ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) ++ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); ++ gtk_widget_destroy(dialog); ++ ++ if (filename) ++ { ++ char *basename = strrchr(filename, '/'); ++ if (!basename) /* wtf? */ ++ goto free_and_ret; ++ basename++; ++ ++ struct stat statbuf; ++ if (stat(filename, &statbuf) != 0 || !S_ISREG(statbuf.st_mode)) ++ goto free_and_ret; ++ ++ struct problem_item *item = get_problem_data_item_or_NULL(g_cd, basename); ++ if (!item || (item->flags & CD_FLAG_ISEDITABLE)) ++ { ++ struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); ++ dd = steal_if_needed(dd); ++ bool writable = (dd && dd->locked); ++ dd_close(dd); ++ if (writable) ++ { ++ char *new_name = concat_path_file(g_dump_dir_name, basename); ++ /* TODO: error check */ ++ copy_file(filename, new_name, 0666); ++ free(new_name); ++ reload_problem_data_from_dump_dir(); ++ update_gui_state_from_problem_data(); ++ } ++ } ++ else ++ { ++ /* TODO: show error dialog */ ++ } ++ free_and_ret: ++ g_free(filename); ++ } ++} ++ + + /* Initialization */ + +@@ -1829,83 +1915,6 @@ static void add_pages() + // g_signal_connect(g_tv_details, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL); + } + +-static void save_edited_one_liner(GtkCellRendererText *renderer, +- gchar *tree_path, +- gchar *new_text, +- gpointer user_data) +-{ +- //log("path:'%s' new_text:'%s'", tree_path, new_text); +- +- GtkTreeIter iter; +- if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(g_ls_details), &iter, tree_path)) +- return; +- gchar *item_name = NULL; +- gtk_tree_model_get(GTK_TREE_MODEL(g_ls_details), &iter, +- DETAIL_COLUMN_NAME, &item_name, +- -1); +- if (!item_name) /* paranoia, should never happen */ +- return; +- struct problem_item *item = get_problem_data_item_or_NULL(g_cd, item_name); +- if (item && (item->flags & CD_FLAG_ISEDITABLE)) +- { +- struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); +- dd = steal_if_needed(dd); +- if (dd && dd->locked) +- { +- dd_save_text(dd, item_name, new_text); +- free(item->content); +- item->content = xstrdup(new_text); +- gtk_list_store_set(g_ls_details, &iter, +- DETAIL_COLUMN_VALUE, new_text, +- -1); +- } +- dd_close(dd); +- } +-} +- +-static void on_btn_add_file(GtkButton *button) +-{ +- GtkWidget *dialog = gtk_file_chooser_dialog_new( +- "Attach File", +- GTK_WINDOW(g_assistant), +- GTK_FILE_CHOOSER_ACTION_OPEN, +- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, +- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, +- NULL +- ); +- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) +- { +- char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); +- +- char *basename = strrchr(filename, '/'); +- if (!basename) /* wtf? */ +- goto free_and_ret; +- basename++; +- +- struct stat statbuf; +- if (stat(filename, &statbuf) != 0 || !S_ISREG(statbuf.st_mode)) +- goto free_and_ret; +- +- struct problem_item *item = get_problem_data_item_or_NULL(g_cd, basename); +- if (!item || (item->flags & CD_FLAG_ISEDITABLE)) +- { +- char *new_name = concat_path_file(g_dump_dir_name, basename); +- /* TODO: error check */ +- copy_file(filename, new_name, 0666); +- free(new_name); +- reload_problem_data_from_dump_dir(); +- update_gui_state_from_problem_data(); +- } +- else +- { +- /* TODO: error dialog */ +- } +- free_and_ret: +- g_free(filename); +- } +- gtk_widget_destroy(dialog); +-} +- + static void create_details_treeview(void) + { + GtkCellRenderer *renderer; +-- +1.7.6 + diff --git a/0005-wizard.glade-glade-generates-class-GtkBox-which-does.patch b/0005-wizard.glade-glade-generates-class-GtkBox-which-does.patch new file mode 100644 index 0000000..547cc6b --- /dev/null +++ b/0005-wizard.glade-glade-generates-class-GtkBox-which-does.patch @@ -0,0 +1,27 @@ +From 94660528f9423f7ef1cfd158627ce4208b01cf59 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 19 Jul 2011 13:24:57 +0200 +Subject: [PATCH 05/12] wizard.glade: glade generates class="GtkBox" which + doesn't work, -> GtkHBox + +Signed-off-by: Denys Vlasenko +--- + src/gui-wizard-gtk/wizard.glade | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/gui-wizard-gtk/wizard.glade b/src/gui-wizard-gtk/wizard.glade +index ba8b09a..787b7f8 100644 +--- a/src/gui-wizard-gtk/wizard.glade ++++ b/src/gui-wizard-gtk/wizard.glade +@@ -686,7 +686,7 @@ + + + +- ++ + True + False + +-- +1.7.6 + diff --git a/0006-support-interactive-plugins-in-GUI-and-CLI.patch b/0006-support-interactive-plugins-in-GUI-and-CLI.patch new file mode 100644 index 0000000..6ee443f --- /dev/null +++ b/0006-support-interactive-plugins-in-GUI-and-CLI.patch @@ -0,0 +1,496 @@ +From da506c2b0f396ccb5a3f7c83b8fd976a763dd1ed Mon Sep 17 00:00:00 2001 +From: Michal Toman +Date: Tue, 19 Jul 2011 13:43:15 +0200 +Subject: [PATCH 06/12] support interactive plugins in GUI and CLI + +--- + src/cli/cli-report.c | 19 +----- + src/gui-wizard-gtk/wizard.c | 179 ++++++++++++++++++++++++++++++++++++++++++- + src/include/client.h | 7 ++ + src/include/run_event.h | 1 + + src/lib/client.c | 43 +++++++++-- + src/lib/run_event.c | 72 ++++++++++++++++- + 6 files changed, 288 insertions(+), 33 deletions(-) + +diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c +index 2598a7a..784b37e 100644 +--- a/src/cli/cli-report.c ++++ b/src/cli/cli-report.c +@@ -18,6 +18,7 @@ + #include "internal_libreport.h" + #include "run-command.h" + #include "cli-report.h" ++#include "client.h" + + /* Field separator for the crash report file that is edited by user. */ + #define FIELD_SEP "%----" +@@ -404,24 +405,6 @@ static bool ask_yesno(const char *question) + return 0 == strncmp(answer, yes, strlen(yes)); + } + +-/* Returns true if echo has been changed from another state. */ +-static bool set_echo(bool enable) +-{ +- struct termios t; +- if (tcgetattr(STDIN_FILENO, &t) < 0) +- return false; +- +- /* No change needed? */ +- if ((bool)(t.c_lflag & ECHO) == enable) +- return false; +- +- t.c_lflag ^= ECHO; +- if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) +- perror_msg_and_die("tcsetattr"); +- +- return true; +-} +- + /* Returns true if the string contains the specified number. */ + static bool is_number_in_string(unsigned number, const char *str) + { +diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c +index 847e84c..b100c13 100644 +--- a/src/gui-wizard-gtk/wizard.c ++++ b/src/gui-wizard-gtk/wizard.c +@@ -17,6 +17,7 @@ + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #include ++#include "client.h" + #include "internal_libreport_gtk.h" + #include "wizard.h" + +@@ -1051,14 +1052,186 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g + + /* Read and insert the output into the log pane */ + char buf[257]; /* usually we get one line, no need to have big buf */ ++ char *msg; /* one line */ ++ char *newline; ++ char *raw; + int r; +- while ((r = read(evd->fd, buf, sizeof(buf)-1)) > 0) ++ struct strbuf *line = strbuf_new(); ++ ++ int alert_prefix_len = strlen(REPORT_PREFIX_ALERT); ++ int ask_prefix_len = strlen(REPORT_PREFIX_ASK); ++ int ask_yes_no_prefix_len = strlen(REPORT_PREFIX_ASK_YES_NO); ++ int ask_password_prefix_len = strlen(REPORT_PREFIX_ASK_PASSWORD); ++ ++ /* read buffered and split lines */ ++ while ((r = read(evd->fd, buf, sizeof(buf) - 1)) > 0) + { + buf[r] = '\0'; +- append_to_textview(evd->tv_log, buf); +- save_to_event_log(evd, buf); ++ raw = buf; ++ ++ /* split lines in the current buffer */ ++ while ((newline = strchr(raw, '\n')) != NULL) ++ { ++ *newline = '\0'; ++ /* finish line */ ++ strbuf_append_str(line, raw); ++ strbuf_append_char(line, '\n'); ++ ++ msg = line->buf; ++ ++ /* alert dialog */ ++ if (strncmp(REPORT_PREFIX_ALERT, msg, alert_prefix_len) == 0) ++ { ++ msg += alert_prefix_len; ++ ++ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), ++ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, ++ GTK_MESSAGE_WARNING, ++ GTK_BUTTONS_CLOSE, ++ msg); ++ ++ gtk_dialog_run(GTK_DIALOG(dialog)); ++ gtk_widget_destroy(dialog); ++ } ++ /* ask dialog with textbox */ ++ else if (strncmp(REPORT_PREFIX_ASK, msg, ask_prefix_len) == 0) ++ { ++ msg += ask_prefix_len; ++ ++ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), ++ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, ++ GTK_MESSAGE_QUESTION, ++ GTK_BUTTONS_OK_CANCEL, ++ msg); ++ ++ GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); ++ GtkWidget *textbox = gtk_entry_new(); ++ gtk_entry_set_editable(GTK_ENTRY(textbox), TRUE); ++ gtk_box_pack_start(GTK_BOX(vbox), textbox, TRUE, TRUE, 0); ++ gtk_widget_show(textbox); ++ ++ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) ++ { ++ const char *text = gtk_entry_get_text(GTK_ENTRY(textbox)); ++ char *response = xasprintf("%s\n", text); ++ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) ++ { ++ free(response); ++ VERB1 perror_msg("Unable to write %s\\n to child's stdin", text); ++ return FALSE; ++ } ++ ++ free(response); ++ } ++ else ++ { ++ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) ++ { ++ VERB1 perror_msg("Unable to write \\n to child's stdin"); ++ return FALSE; ++ } ++ } ++ ++ gtk_widget_destroy(textbox); ++ gtk_widget_destroy(dialog); ++ } ++ /* ask dialog with passwordbox */ ++ else if (strncmp(REPORT_PREFIX_ASK_PASSWORD, msg, ask_password_prefix_len) == 0) ++ { ++ msg += ask_password_prefix_len; ++ ++ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), ++ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, ++ GTK_MESSAGE_QUESTION, ++ GTK_BUTTONS_OK_CANCEL, ++ msg); ++ ++ GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); ++ GtkWidget *textbox = gtk_entry_new(); ++ gtk_entry_set_editable(GTK_ENTRY(textbox), TRUE); ++ gtk_entry_set_visibility(GTK_ENTRY(textbox), FALSE); ++ gtk_box_pack_start(GTK_BOX(vbox), textbox, TRUE, TRUE, 0); ++ gtk_widget_show(textbox); ++ ++ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) ++ { ++ const char *text = gtk_entry_get_text(GTK_ENTRY(textbox)); ++ char *response = xasprintf("%s\n", text); ++ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) ++ { ++ free(response); ++ VERB1 perror_msg("Unable to write %s\\n to child's stdin", text); ++ return FALSE; ++ } ++ ++ free(response); ++ } ++ else ++ { ++ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) ++ { ++ VERB1 perror_msg("Unable to write \\n to child's stdin"); ++ return FALSE; ++ } ++ } ++ ++ gtk_widget_destroy(textbox); ++ gtk_widget_destroy(dialog); ++ } ++ /* yes/no dialog */ ++ else if (strncmp(REPORT_PREFIX_ASK_YES_NO, msg, ask_yes_no_prefix_len) == 0) ++ { ++ msg += ask_yes_no_prefix_len; ++ ++ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), ++ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, ++ GTK_MESSAGE_QUESTION, ++ GTK_BUTTONS_YES_NO, ++ msg); ++ ++ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) ++ { ++ char *yes = _("y"); ++ char *response = xasprintf("%s\n", yes); ++ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) ++ { ++ free(response); ++ VERB1 perror_msg("Unable to write %s\\n to child's stdin", yes); ++ return FALSE; ++ } ++ ++ free(response); ++ } ++ else ++ { ++ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) ++ { ++ VERB1 perror_msg("Unable to write \\n to child's stdin"); ++ return FALSE; ++ } ++ } ++ ++ gtk_widget_destroy(dialog); ++ } ++ /* no special prefix - forward to log */ ++ else ++ { ++ append_to_textview(evd->tv_log, msg); ++ save_to_event_log(evd, msg); ++ } ++ ++ strbuf_clear(line); ++ ++ /* jump to next line */ ++ raw = newline + 1; ++ } ++ ++ /* beginning of next line. the line continues by next read() */ ++ strbuf_append_str(line, raw); + } + ++ strbuf_free(line); ++ + if (r < 0 && errno == EAGAIN) + /* We got all buffered data, but fd is still open. Done for now */ + return TRUE; /* "please don't remove this event (yet)" */ +diff --git a/src/include/client.h b/src/include/client.h +index bbd2f10..8074145 100644 +--- a/src/include/client.h ++++ b/src/include/client.h +@@ -22,18 +22,25 @@ + + #define REPORT_PREFIX_ASK_YES_NO "ASK_YES_NO " + #define REPORT_PREFIX_ASK "ASK " ++#define REPORT_PREFIX_ASK_PASSWORD "ASK_PASSWORD " + #define REPORT_PREFIX_ALERT "ALERT " + + #ifdef __cplusplus + extern "C" { + #endif + ++#define set_echo libreport_set_echo ++int set_echo(int enable); ++ + #define ask_yes_no libreport_ask_yes_no + int ask_yes_no(const char *question); + + #define ask libreport_ask + char *ask(const char *question, char *response, int response_len); + ++#define ask_password libreport_ask_password ++char *ask_password(const char *question, char *response, int response_len); ++ + #define alert libreport_alert + void alert(const char *message); + +diff --git a/src/include/run_event.h b/src/include/run_event.h +index f7ae9ed..43730ce 100644 +--- a/src/include/run_event.h ++++ b/src/include/run_event.h +@@ -44,6 +44,7 @@ struct run_event_state { + GList *rule_list; + pid_t command_pid; + int command_out_fd; ++ int command_in_fd; + }; + struct run_event_state *new_run_event_state(void); + void free_run_event_state(struct run_event_state *state); +diff --git a/src/lib/client.c b/src/lib/client.c +index 88a995b..103828b 100644 +--- a/src/lib/client.c ++++ b/src/lib/client.c +@@ -25,6 +25,24 @@ static int is_slave_mode() + return getenv("REPORT_CLIENT_SLAVE") != NULL; + } + ++/* Returns 1 if echo has been changed from another state. */ ++int set_echo(int enable) ++{ ++ struct termios t; ++ if (tcgetattr(STDIN_FILENO, &t) < 0) ++ return 0; ++ ++ /* No change needed? */ ++ if ((t.c_lflag & ECHO) == enable) ++ return 0; ++ ++ t.c_lflag ^= ECHO; ++ if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) ++ perror_msg_and_die("tcsetattr"); ++ ++ return 1; ++} ++ + int ask_yes_no(const char *question) + { + const char *yes = _("y"); +@@ -32,12 +50,7 @@ int ask_yes_no(const char *question) + + char *env_response = getenv("REPORT_CLIENT_RESPONSE"); + if (env_response) +- { +- if (strncasecmp(yes, env_response, strlen(yes)) == 0) +- return true; +- if (strncasecmp(no, env_response, strlen(no)) == 0) +- return false; +- } ++ return strncasecmp(yes, env_response, strlen(yes)) == 0; + + if (is_slave_mode()) + printf(REPORT_PREFIX_ASK_YES_NO "%s\n", question); +@@ -48,7 +61,7 @@ int ask_yes_no(const char *question) + + char response[16]; + if (NULL == fgets(response, sizeof(response), stdin)) +- return false; ++ return 0; + + return strncasecmp(yes, response, strlen(yes)) == 0; + } +@@ -65,6 +78,22 @@ char *ask(const char *question, char *response, int response_len) + return fgets(response, response_len, stdin); + } + ++char *ask_password(const char *question, char *response, int response_len) ++{ ++ if (is_slave_mode()) ++ printf(REPORT_PREFIX_ASK_PASSWORD "%s\n", question); ++ else ++ printf("%s ", question); ++ ++ fflush(stdout); ++ ++ set_echo(false); ++ char *result = fgets(response, response_len, stdin); ++ set_echo(true); ++ ++ return result; ++} ++ + void alert(const char *message) + { + if (is_slave_mode()) +diff --git a/src/lib/run_event.c b/src/lib/run_event.c +index 0594bde..ba9920c 100644 +--- a/src/lib/run_event.c ++++ b/src/lib/run_event.c +@@ -18,6 +18,7 @@ + */ + #include + #include ++#include "client.h" + #include "internal_libreport.h" + + struct run_event_state *new_run_event_state() +@@ -393,7 +394,7 @@ 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]; ++ char *env_vec[4]; + /* 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... +@@ -402,7 +403,8 @@ int spawn_next_command(struct run_event_state *state, + env_vec[0] = xasprintf("DUMP_DIR=%s", (full_name ? full_name : dump_dir_name)); + free(full_name); + env_vec[1] = xasprintf("EVENT=%s", event); +- env_vec[2] = NULL; ++ env_vec[2] = xasprintf("REPORT_CLIENT_SLAVE=1"); ++ env_vec[3] = NULL; + + char *argv[4]; + argv[0] = (char*)"/bin/sh"; // TODO: honor $SHELL? +@@ -412,7 +414,7 @@ int spawn_next_command(struct run_event_state *state, + + int pipefds[2]; + state->command_pid = fork_execv_on_steroids( +- EXECFLG_INPUT_NUL + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, ++ EXECFLG_INPUT + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, + argv, + pipefds, + /* env_vec: */ env_vec, +@@ -420,9 +422,11 @@ int spawn_next_command(struct run_event_state *state, + /* uid(unused): */ 0 + ); + state->command_out_fd = pipefds[0]; ++ state->command_in_fd = pipefds[1]; + + free(env_vec[0]); + free(env_vec[1]); ++ free(env_vec[2]); + free(cmd); + + return 0; +@@ -447,10 +451,68 @@ int run_event_on_dir_name(struct run_event_state *state, + if (!fp) + die_out_of_memory(); + char *buf; ++ char *msg; ++ ++ int alert_prefix_len = strlen(REPORT_PREFIX_ALERT); ++ int ask_prefix_len = strlen(REPORT_PREFIX_ASK); ++ int ask_yes_no_prefix_len = strlen(REPORT_PREFIX_ASK_YES_NO); ++ int ask_password_prefix_len = strlen(REPORT_PREFIX_ASK_PASSWORD); ++ + while ((buf = xmalloc_fgetline(fp)) != NULL) + { +- if (state->logging_callback) +- buf = state->logging_callback(buf, state->logging_param); ++ msg = buf; ++ ++ /* just cut off prefix, no waiting */ ++ if (strncmp(REPORT_PREFIX_ALERT, msg, alert_prefix_len) == 0) ++ { ++ msg += alert_prefix_len; ++ printf("%s\n", msg); ++ fflush(stdout); ++ } ++ /* wait for y/N response on the same line */ ++ else if (strncmp(REPORT_PREFIX_ASK_YES_NO, msg, ask_yes_no_prefix_len) == 0) ++ { ++ msg += ask_yes_no_prefix_len; ++ printf("%s [%s/%s] ", msg, _("y"), _("N")); ++ fflush(stdout); ++ char buf[16]; ++ if (!fgets(buf, sizeof(buf), stdin)) ++ buf[0] = '\0'; ++ ++ if (write(state->command_in_fd, buf, strlen(buf)) < 0) ++ perror_msg_and_die("write"); ++ } ++ /* wait for the string on the same line */ ++ else if (strncmp(REPORT_PREFIX_ASK, msg, ask_prefix_len) == 0) ++ { ++ msg += ask_prefix_len; ++ printf("%s ", msg); ++ fflush(stdout); ++ char buf[256]; ++ if (!fgets(buf, sizeof(buf), stdin)) ++ buf[0] = '\0'; ++ ++ if (write(state->command_in_fd, buf, strlen(buf)) < 0) ++ perror_msg_and_die("write"); ++ } ++ /* set echo off and wait for password on the same line */ ++ else if (strncmp(REPORT_PREFIX_ASK_PASSWORD, msg, ask_password_prefix_len) == 0) ++ { ++ msg += ask_password_prefix_len; ++ printf("%s ", msg); ++ fflush(stdout); ++ char buf[256]; ++ set_echo(false); ++ if (!fgets(buf, sizeof(buf), stdin)) ++ buf[0] = '\0'; ++ set_echo(true); ++ ++ if (write(state->command_in_fd, buf, strlen(buf)) < 0) ++ perror_msg_and_die("write"); ++ } ++ /* no special prefix -> forward to log if applicable */ ++ else if (state->logging_callback) ++ msg = state->logging_callback(msg, state->logging_param); + free(buf); + } + fclose(fp); /* Got EOF, close. This also closes state->command_out_fd */ +-- +1.7.6 + diff --git a/0007-wizard-if-more-than-one-reporter-is-chosen-select-al.patch b/0007-wizard-if-more-than-one-reporter-is-chosen-select-al.patch new file mode 100644 index 0000000..d5ac2b1 --- /dev/null +++ b/0007-wizard-if-more-than-one-reporter-is-chosen-select-al.patch @@ -0,0 +1,150 @@ +From 929176564c779031bec181474364923d6869e30e Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 19 Jul 2011 14:37:41 +0200 +Subject: [PATCH 07/12] wizard: if more than one reporter is chosen, select + all items. Helps with bz#723021 + +Before this change, in such case all items were unselected. + +Signed-off-by: Denys Vlasenko +--- + src/gui-wizard-gtk/wizard.c | 100 +++++++++++++++++++++++------------------- + 1 files changed, 55 insertions(+), 45 deletions(-) + +diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c +index b100c13..3eea380 100644 +--- a/src/gui-wizard-gtk/wizard.c ++++ b/src/gui-wizard-gtk/wizard.c +@@ -1655,74 +1655,84 @@ static void on_page_prepare(GtkAssistant *assistant, GtkWidget *page, gpointer u + /* Based on selected reporter, update item checkboxes */ + event_config_t *cfg = get_event_config(g_reporter_events_selected ? g_reporter_events_selected : ""); + //log("%s: event:'%s', cfg:'%p'", __func__, g_reporter_events_selected, cfg); ++ int allowed_by_reporter = 1; ++ int default_by_reporter = 1; + if (cfg) + { + /* Default settings are... */ +- int allowed_by_reporter = 1; + if (cfg->ec_exclude_items_always && strcmp(cfg->ec_exclude_items_always, "*") == 0) + allowed_by_reporter = 0; +- int default_by_reporter = allowed_by_reporter; ++ default_by_reporter = allowed_by_reporter; + if (cfg->ec_exclude_items_by_default && strcmp(cfg->ec_exclude_items_by_default, "*") == 0) + default_by_reporter = 0; ++ } + +- GHashTableIter iter; +- char *name; +- struct problem_item *item; +- g_hash_table_iter_init(&iter, g_cd); +- while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&item)) ++ GHashTableIter iter; ++ char *name; ++ struct problem_item *item; ++ g_hash_table_iter_init(&iter, g_cd); ++ while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&item)) ++ { ++ /* Decide whether item is allowed, required, and what's the default */ ++ item->allowed_by_reporter = allowed_by_reporter; ++ if (cfg) + { +- /* Decide whether item is allowed, required, and what's the default */ +- item->allowed_by_reporter = allowed_by_reporter; + if (is_in_comma_separated_list(name, cfg->ec_exclude_items_always)) + item->allowed_by_reporter = 0; + if ((item->flags & CD_FLAG_BIN) && cfg->ec_exclude_binary_items) + item->allowed_by_reporter = 0; ++ } + +- item->default_by_reporter = item->allowed_by_reporter ? default_by_reporter : 0; ++ item->default_by_reporter = item->allowed_by_reporter ? default_by_reporter : 0; ++ if (cfg) ++ { + if (is_in_comma_separated_list(name, cfg->ec_exclude_items_by_default)) + item->default_by_reporter = 0; + if (is_in_comma_separated_list(name, cfg->ec_include_items_by_default)) + item->allowed_by_reporter = item->default_by_reporter = 1; ++ } + +- item->required_by_reporter = 0; ++ item->required_by_reporter = 0; ++ if (cfg) ++ { + if (is_in_comma_separated_list(name, cfg->ec_requires_items)) + item->default_by_reporter = item->allowed_by_reporter = item->required_by_reporter = 1; ++ } + +- int cur_value; +- if (item->selected_by_user == 0) +- cur_value = item->default_by_reporter; +- else +- cur_value = !!(item->selected_by_user + 1); /* map -1,1 to 0,1 */ +- +- //log("%s: '%s' allowed:%d reqd:%d def:%d user:%d", __func__, name, +- // item->allowed_by_reporter, +- // item->required_by_reporter, +- // item->default_by_reporter, +- // item->selected_by_user +- //); +- +- /* Find corresponding line and update checkbox */ +- GtkTreeIter iter; +- if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_ls_details), &iter)) +- { +- do { +- gchar *item_name = NULL; +- gtk_tree_model_get(GTK_TREE_MODEL(g_ls_details), &iter, +- DETAIL_COLUMN_NAME, &item_name, +- -1); +- if (!item_name) /* paranoia, should never happen */ +- continue; +- int differ = strcmp(name, item_name); +- g_free(item_name); +- if (differ) +- continue; +- gtk_list_store_set(g_ls_details, &iter, +- DETAIL_COLUMN_CHECKBOX, cur_value, ++ int cur_value; ++ if (item->selected_by_user == 0) ++ cur_value = item->default_by_reporter; ++ else ++ cur_value = !!(item->selected_by_user + 1); /* map -1,1 to 0,1 */ ++ ++ //log("%s: '%s' allowed:%d reqd:%d def:%d user:%d", __func__, name, ++ // item->allowed_by_reporter, ++ // item->required_by_reporter, ++ // item->default_by_reporter, ++ // item->selected_by_user ++ //); ++ ++ /* Find corresponding line and update checkbox */ ++ GtkTreeIter iter; ++ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_ls_details), &iter)) ++ { ++ do { ++ gchar *item_name = NULL; ++ gtk_tree_model_get(GTK_TREE_MODEL(g_ls_details), &iter, ++ DETAIL_COLUMN_NAME, &item_name, + -1); +- //log("%s: changed gtk_list_store_set to %d", __func__, (item->allowed_by_reporter && item->selected_by_user >= 0)); +- break; +- } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_ls_details), &iter)); +- } ++ if (!item_name) /* paranoia, should never happen */ ++ continue; ++ int differ = strcmp(name, item_name); ++ g_free(item_name); ++ if (differ) ++ continue; ++ gtk_list_store_set(g_ls_details, &iter, ++ DETAIL_COLUMN_CHECKBOX, cur_value, ++ -1); ++ //log("%s: changed gtk_list_store_set to %d", __func__, (item->allowed_by_reporter && item->selected_by_user >= 0)); ++ break; ++ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_ls_details), &iter)); + } + } + } +-- +1.7.6 + diff --git a/0008-added-xml-file-for-Logger-event.patch b/0008-added-xml-file-for-Logger-event.patch new file mode 100644 index 0000000..d570e61 --- /dev/null +++ b/0008-added-xml-file-for-Logger-event.patch @@ -0,0 +1,84 @@ +From ddbdc3f2451e061f57b350379d2daecb65bcd7fc Mon Sep 17 00:00:00 2001 +From: Jiri Moskovcak +Date: Wed, 20 Jul 2011 14:25:34 +0200 +Subject: [PATCH 08/12] added xml file for Logger event + +--- + src/plugins/Makefile.am | 2 ++ + src/plugins/print_event.conf | 2 +- + src/plugins/report_Logger.conf | 4 ++-- + src/plugins/report_Logger.xml.in | 25 +++++++++++++++++++++++++ + 5 files changed, 31 insertions(+), 3 deletions(-) + create mode 100644 src/plugins/report_Logger.xml.in + +diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am +index 4435357..d616ee5 100644 +--- a/src/plugins/Makefile.am ++++ b/src/plugins/Makefile.am +@@ -23,6 +23,7 @@ dist_events_DATA = \ + report_Bugzilla.xml \ + report_Bugzilla.conf \ + report_Logger.conf \ ++ report_Logger.xml \ + report_Mailx.xml \ + report_RHTSupport.xml \ + report_Kerneloops.xml +@@ -62,6 +63,7 @@ EXTRA_DIST = \ + report_Bugzilla.xml.in \ + report_Bugzilla.conf \ + report_Logger.conf \ ++ report_Logger.xml.in \ + report_Mailx.xml.in \ + report_RHTSupport.xml.in \ + report_Kerneloops.xml.in +diff --git a/src/plugins/print_event.conf b/src/plugins/print_event.conf +index 7b94aba..6e6e38e 100644 +--- a/src/plugins/print_event.conf ++++ b/src/plugins/print_event.conf +@@ -1,2 +1,2 @@ + EVENT=report_Logger +- reporter-print -o "${Log_File:-/tmp/abrt.log}" -a "${Append:-no}" -r ++ reporter-print -o "${Logger_Log_File:-/tmp/abrt.log}" -a "${Logger_Append:-no}" -r +diff --git a/src/plugins/report_Logger.conf b/src/plugins/report_Logger.conf +index d885ce5..45f6b5d 100644 +--- a/src/plugins/report_Logger.conf ++++ b/src/plugins/report_Logger.conf +@@ -1,2 +1,2 @@ +-Log_File=/tmp/abrt.log +-Append=yes ++Logger_Log_File=/tmp/abrt.log ++Logger_Append=yes +diff --git a/src/plugins/report_Logger.xml.in b/src/plugins/report_Logger.xml.in +new file mode 100644 +index 0000000..f7230e0 +--- /dev/null ++++ b/src/plugins/report_Logger.xml.in +@@ -0,0 +1,25 @@ ++ ++ ++ <_name>Logger ++ <_description>Save the report locally ++ ++ ++ coredump ++ ++ no ++ ++ ++ ++ ++ ++ ++ +-- +1.7.6 + diff --git a/0009-report-cli-don-t-crash-when-invalid-analyzer-is-sele.patch b/0009-report-cli-don-t-crash-when-invalid-analyzer-is-sele.patch new file mode 100644 index 0000000..d725299 --- /dev/null +++ b/0009-report-cli-don-t-crash-when-invalid-analyzer-is-sele.patch @@ -0,0 +1,26 @@ +From 68b8aaa4f2c54fbdf9fa3bacfe93c8fcefa35067 Mon Sep 17 00:00:00 2001 +From: Miroslav Lichvar +Date: Wed, 20 Jul 2011 15:53:32 +0200 +Subject: [PATCH 09/12] report-cli: don't crash when invalid analyzer is + selected (trac#294) + +--- + src/cli/cli-report.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c +index 784b37e..6ec7f96 100644 +--- a/src/cli/cli-report.c ++++ b/src/cli/cli-report.c +@@ -620,7 +620,7 @@ char *select_event_option(GList *list_options) + continue; + + picked = xatou(answer); +- if (picked > count) ++ if (picked > count || picked < 1) + { + fprintf(stdout, _("You have chosen number out of range")); + fprintf(stdout, "\n"); +-- +1.7.6 + diff --git a/0010-Add-another-reporting-flag-LIBREPORT_GETPID.patch b/0010-Add-another-reporting-flag-LIBREPORT_GETPID.patch new file mode 100644 index 0000000..b8872d0 --- /dev/null +++ b/0010-Add-another-reporting-flag-LIBREPORT_GETPID.patch @@ -0,0 +1,94 @@ +From 6a69e7ad5186709bd3dbaa8e843a1e16b39bb501 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Thu, 21 Jul 2011 09:51:57 +0200 +Subject: [PATCH 10/12] Add another reporting flag, LIBREPORT_GETPID. + +This flag means "return the pid of reporting process". + +IOW: LIBREPORT_NOWAIT will reparent reporter to init +and return 0, LIBREPORT_NOWAIT | LIBREPORT_GETPID will not, +and will return pid. + +Signed-off-by: Denys Vlasenko +--- + src/include/report.h | 9 ++++++--- + src/lib/report.c | 14 +++++++++++--- + src/report-python/reportmodule.c | 1 + + 3 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/src/include/report.h b/src/include/report.h +index 18bb20b..410a24d 100644 +--- a/src/include/report.h ++++ b/src/include/report.h +@@ -28,10 +28,13 @@ extern "C" { + enum { + LIBREPORT_NOWAIT = 0, + LIBREPORT_WAIT = (1 << 0), /* wait for report to finish and reload the problem data */ +- LIBREPORT_ANALYZE = (1 << 1), /* run analyzers? */ ++ LIBREPORT_GETPID = (1 << 1), /* return pid of child. Use with LIBREPORT_NOWAIT. */ ++ /* Note: without LIBREPORT_GETPID, child will be detached */ ++ /* (reparented to init) */ ++ LIBREPORT_ANALYZE = (1 << 2), /* run analyzers? */ + /* ("run reporters" is always on, has no flag (for now?)) */ +- LIBREPORT_RELOAD_DATA = (1 << 3), /* reload problem data after run (needs WAIT) */ +- LIBREPORT_DEL_DIR = (1 << 4), /* delete directory after reporting */ ++ LIBREPORT_RELOAD_DATA = (1 << 5), /* reload problem data after run (needs WAIT) */ ++ LIBREPORT_DEL_DIR = (1 << 6), /* delete directory after reporting */ + }; + + int report_problem_in_dir(const char *dirname, int flags); +diff --git a/src/lib/report.c b/src/lib/report.c +index aaf5326..3c365ae 100644 +--- a/src/lib/report.c ++++ b/src/lib/report.c +@@ -74,9 +74,10 @@ int report_problem_in_dir(const char *dirname, int flags) + */ + signal(SIGCHLD, SIG_DFL); + +- if (!(flags & LIBREPORT_WAIT)) ++ if (!(flags & (LIBREPORT_WAIT | LIBREPORT_GETPID))) + { +- /* Caller doesn't want to wait for completion. ++ /* Caller doesn't want to wait for completion (!LIBREPORT_WAIT), ++ * and doesn't want to have pid returned (!LIBREPORT_GETPID). + * Create a grandchild, and then exit. + * This reparents grandchild to init, and makes waitpid + * in parent detect our exit and return almost immediately. +@@ -120,6 +121,13 @@ int report_problem_in_dir(const char *dirname, int flags) + } + + /* parent */ ++ if (!(flags & LIBREPORT_WAIT) && (flags & LIBREPORT_GETPID)) ++ return pid; ++ ++ /* we are here either if LIBREPORT_WAIT (caller wants exitcode) ++ * or !LIBREPORT_GETPID (caller doesn't want to have a child). ++ * In both cases, we need to wait for child: ++ */ + int status; + do + pid = waitpid(pid, &status, 0); +@@ -150,7 +158,7 @@ int report_problem_in_memory(problem_data_t *pd, int flags) + dd_close(dd); + VERB2 log("Temp problem dir: '%s'", dir_name); + +- if (!(flags & LIBREPORT_WAIT)) ++ if (flags & LIBREPORT_NOWAIT) + flags |= LIBREPORT_DEL_DIR; + result = report_problem_in_dir(dir_name, flags); + +diff --git a/src/report-python/reportmodule.c b/src/report-python/reportmodule.c +index 3d802f9..b99ed49 100644 +--- a/src/report-python/reportmodule.c ++++ b/src/report-python/reportmodule.c +@@ -90,6 +90,7 @@ init_pyreport(void) + /* for include/report/report.h */ + PyModule_AddObject(m, "LIBREPORT_NOWAIT" , Py_BuildValue("i", LIBREPORT_NOWAIT )); + PyModule_AddObject(m, "LIBREPORT_WAIT" , Py_BuildValue("i", LIBREPORT_WAIT )); ++ PyModule_AddObject(m, "LIBREPORT_GETPID" , Py_BuildValue("i", LIBREPORT_GETPID )); + PyModule_AddObject(m, "LIBREPORT_ANALYZE" , Py_BuildValue("i", LIBREPORT_ANALYZE )); + PyModule_AddObject(m, "LIBREPORT_RELOAD_DATA", Py_BuildValue("i", LIBREPORT_RELOAD_DATA)); + PyModule_AddObject(m, "LIBREPORT_DEL_DIR" , Py_BuildValue("i", LIBREPORT_DEL_DIR )); +-- +1.7.6 + diff --git a/0011-add-python-bindings-for-interactive-plugins.patch b/0011-add-python-bindings-for-interactive-plugins.patch new file mode 100644 index 0000000..9059841 --- /dev/null +++ b/0011-add-python-bindings-for-interactive-plugins.patch @@ -0,0 +1,268 @@ +From 02e0e56b5903f5f0e905f20be8413914ab6aa529 Mon Sep 17 00:00:00 2001 +From: Michal Toman +Date: Thu, 21 Jul 2011 14:25:32 +0200 +Subject: [PATCH 11/12] add python bindings for interactive plugins + +--- + configure.ac | 1 + + src/Makefile.am | 2 +- + src/client-python/Makefile.am | 29 +++++++++++++ + src/client-python/__init__.py | 15 +++++++ + src/client-python/client.c | 83 ++++++++++++++++++++++++++++++++++++++ + src/client-python/clientmodule.c | 42 +++++++++++++++++++ + src/client-python/common.h | 27 ++++++++++++ + 8 files changed, 199 insertions(+), 1 deletions(-) + create mode 100644 src/client-python/Makefile.am + create mode 100644 src/client-python/__init__.py + create mode 100644 src/client-python/client.c + create mode 100644 src/client-python/clientmodule.c + create mode 100644 src/client-python/common.h + +diff --git a/configure.ac b/configure.ac +index 61f16ae..4b01af6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -126,6 +126,7 @@ AC_CONFIG_FILES([ + src/cli/Makefile + src/report-newt/Makefile + src/plugins/Makefile ++ src/client-python/Makefile + po/Makefile.in + ]) + +diff --git a/src/Makefile.am b/src/Makefile.am +index 24dfeb2..3a6da3f 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1 +1 @@ +-SUBDIRS = include lib plugins report-python gtk-helpers gui-wizard-gtk cli report-newt ++SUBDIRS = include lib plugins report-python gtk-helpers gui-wizard-gtk cli report-newt client-python +diff --git a/src/client-python/Makefile.am b/src/client-python/Makefile.am +new file mode 100644 +index 0000000..5a2a58f +--- /dev/null ++++ b/src/client-python/Makefile.am +@@ -0,0 +1,29 @@ ++clientexecdir = $(pyexecdir)/reportclient ++ ++clientexec_PYTHON = \ ++ __init__.py ++ ++clientexec_LTLIBRARIES = _reportclient.la ++ ++_reportclient_la_SOURCES = \ ++ clientmodule.c \ ++ client.c \ ++ common.h ++_reportclient_la_CPPFLAGS = \ ++ -I$(srcdir)/../include/report -I$(srcdir)/../include \ ++ -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)\" \ ++ $(GLIB_CFLAGS) \ ++ $(PYTHON_CFLAGS) \ ++ -D_GNU_SOURCE \ ++ -Wall -Wwrite-strings -Werror ++_reportclient_la_LDFLAGS = \ ++ -module \ ++ -avoid-version \ ++ -export-symbols-regex init_reportclient ++_reportclient_la_LIBADD = \ ++ ../lib/libreport.la +diff --git a/src/client-python/__init__.py b/src/client-python/__init__.py +new file mode 100644 +index 0000000..6114b5a +--- /dev/null ++++ b/src/client-python/__init__.py +@@ -0,0 +1,15 @@ ++# 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. ++ ++from _reportclient import * +diff --git a/src/client-python/client.c b/src/client-python/client.c +new file mode 100644 +index 0000000..7177ae3 +--- /dev/null ++++ b/src/client-python/client.c +@@ -0,0 +1,83 @@ ++/* ++ Copyright (C) 2010 Abrt team. ++ Copyright (C) 2010 RedHat inc. ++ ++ 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 ++ ++#include "common.h" ++ ++/* C: void alert(const char *message); */ ++PyObject *p_alert(PyObject *pself, PyObject *args) ++{ ++ const char *message; ++ if (!PyArg_ParseTuple(args, "s", &message)) ++ { ++ return NULL; ++ } ++ alert(message); ++ Py_RETURN_NONE; ++} ++ ++/* C: char *ask(const char *question, char *response, int response_len); */ ++PyObject *p_ask(PyObject *pself, PyObject *args) ++{ ++ const char *question; ++ if (!PyArg_ParseTuple(args, "s", &question)) ++ { ++ return NULL; ++ } ++ ++ char response[256]; ++ if (!ask(question, response, sizeof(response))) ++ { ++ Py_RETURN_NONE; ++ } ++ ++ return Py_BuildValue("s", response); ++} ++ ++/* C: char *ask_password(const char *question, char *response, int response_len); */ ++PyObject *p_ask_password(PyObject *pself, PyObject *args) ++{ ++ const char *question; ++ if (!PyArg_ParseTuple(args, "s", &question)) ++ { ++ return NULL; ++ } ++ ++ char response[256]; ++ if (!ask_password(question, response, sizeof(response))) ++ { ++ Py_RETURN_NONE; ++ } ++ ++ return Py_BuildValue("s", response); ++} ++ ++/* C: int ask_yes_no(const char *question); */ ++PyObject *p_ask_yes_no(PyObject *pself, PyObject *args) ++{ ++ const char *question; ++ if (!PyArg_ParseTuple(args, "s", &question)) ++ { ++ return NULL; ++ } ++ ++ int response = ask_yes_no(question); ++ ++ return Py_BuildValue("i", response); ++} +diff --git a/src/client-python/clientmodule.c b/src/client-python/clientmodule.c +new file mode 100644 +index 0000000..e4584dd +--- /dev/null ++++ b/src/client-python/clientmodule.c +@@ -0,0 +1,42 @@ ++/* ++ Copyright (C) 2010 Abrt team. ++ Copyright (C) 2010 RedHat inc. ++ ++ 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 ++ ++#include "common.h" ++ ++static PyMethodDef module_methods[] = { ++ /* method_name, func, flags, doc_string */ ++ /* for include/client.h */ ++ { "alert" , p_alert , METH_VARARGS }, ++ { "ask" , p_ask , METH_VARARGS }, ++ { "ask_password" , p_ask_password , METH_VARARGS }, ++ { "ask_yes_no" , p_ask_yes_no , METH_VARARGS }, ++ { NULL } ++}; ++ ++#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ ++#define PyMODINIT_FUNC void ++#endif ++PyMODINIT_FUNC ++init_reportclient(void) ++{ ++ PyObject *m = Py_InitModule("_reportclient", module_methods); ++ if (!m) ++ printf("m == NULL\n"); ++} +diff --git a/src/client-python/common.h b/src/client-python/common.h +new file mode 100644 +index 0000000..02f685f +--- /dev/null ++++ b/src/client-python/common.h +@@ -0,0 +1,27 @@ ++/* ++ Copyright (C) 2009 Abrt team. ++ Copyright (C) 2009 RedHat inc. ++ ++ 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 ++ ++#include "client.h" ++/* module-level functions */ ++/* for include/client.h */ ++PyObject *p_alert(PyObject *pself, PyObject *args); ++PyObject *p_ask(PyObject *pself, PyObject *args); ++PyObject *p_ask_password(PyObject *pself, PyObject *args); ++PyObject *p_ask_yes_no(PyObject *pself, PyObject *args); +-- +1.7.6 + diff --git a/0012-run_event_on_dir-fix-double-free.patch b/0012-run_event_on_dir-fix-double-free.patch new file mode 100644 index 0000000..8277113 --- /dev/null +++ b/0012-run_event_on_dir-fix-double-free.patch @@ -0,0 +1,32 @@ +From 3ad62d790e546d18d6970e8b49f6f7e0d689c01d Mon Sep 17 00:00:00 2001 +From: Martin Milata +Date: Thu, 21 Jul 2011 15:01:07 +0200 +Subject: [PATCH 12/12] run_event_on_dir: fix double free + +Run_event_on_dir freed the message buffer even if the logging callback +took ownership (like do_log_and_save_line does). Fix that. +--- + src/lib/run_event.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/lib/run_event.c b/src/lib/run_event.c +index ba9920c..77d2819 100644 +--- a/src/lib/run_event.c ++++ b/src/lib/run_event.c +@@ -510,9 +510,11 @@ int run_event_on_dir_name(struct run_event_state *state, + if (write(state->command_in_fd, buf, strlen(buf)) < 0) + perror_msg_and_die("write"); + } +- /* no special prefix -> forward to log if applicable */ ++ /* no special prefix -> forward to log if applicable ++ * note that callback may take ownership of buf by returning NULL */ + else if (state->logging_callback) +- msg = state->logging_callback(msg, state->logging_param); ++ buf = state->logging_callback(buf, state->logging_param); ++ + free(buf); + } + fclose(fp); /* Got EOF, close. This also closes state->command_out_fd */ +-- +1.7.6 + diff --git a/interactive-libreport.patch b/interactive-libreport.patch deleted file mode 100644 index 6f12a24..0000000 --- a/interactive-libreport.patch +++ /dev/null @@ -1,479 +0,0 @@ -diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c -index 2598a7a..784b37e 100644 ---- a/src/cli/cli-report.c -+++ b/src/cli/cli-report.c -@@ -18,6 +18,7 @@ - #include "internal_libreport.h" - #include "run-command.h" - #include "cli-report.h" -+#include "client.h" - - /* Field separator for the crash report file that is edited by user. */ - #define FIELD_SEP "%----" -@@ -404,24 +405,6 @@ static bool ask_yesno(const char *question) - return 0 == strncmp(answer, yes, strlen(yes)); - } - --/* Returns true if echo has been changed from another state. */ --static bool set_echo(bool enable) --{ -- struct termios t; -- if (tcgetattr(STDIN_FILENO, &t) < 0) -- return false; -- -- /* No change needed? */ -- if ((bool)(t.c_lflag & ECHO) == enable) -- return false; -- -- t.c_lflag ^= ECHO; -- if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) -- perror_msg_and_die("tcsetattr"); -- -- return true; --} -- - /* Returns true if the string contains the specified number. */ - static bool is_number_in_string(unsigned number, const char *str) - { -diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c -index 6ed6713..7a0e7e5 100644 ---- a/src/gui-wizard-gtk/wizard.c -+++ b/src/gui-wizard-gtk/wizard.c -@@ -17,6 +17,7 @@ - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - #include -+#include "client.h" - #include "internal_libreport_gtk.h" - #include "wizard.h" - -@@ -1045,14 +1046,186 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g - - /* Read and insert the output into the log pane */ - char buf[257]; /* usually we get one line, no need to have big buf */ -+ char *msg; /* one line */ -+ char *newline; -+ char *raw; - int r; -- while ((r = read(evd->fd, buf, sizeof(buf)-1)) > 0) -+ struct strbuf *line = strbuf_new(); -+ -+ int alert_prefix_len = strlen(REPORT_PREFIX_ALERT); -+ int ask_prefix_len = strlen(REPORT_PREFIX_ASK); -+ int ask_yes_no_prefix_len = strlen(REPORT_PREFIX_ASK_YES_NO); -+ int ask_password_prefix_len = strlen(REPORT_PREFIX_ASK_PASSWORD); -+ -+ /* read buffered and split lines */ -+ while ((r = read(evd->fd, buf, sizeof(buf) - 1)) > 0) - { - buf[r] = '\0'; -- append_to_textview(evd->tv_log, buf); -- save_to_event_log(evd, buf); -+ raw = buf; -+ -+ /* split lines in the current buffer */ -+ while ((newline = strchr(raw, '\n')) != NULL) -+ { -+ *newline = '\0'; -+ /* finish line */ -+ strbuf_append_str(line, raw); -+ strbuf_append_char(line, '\n'); -+ -+ msg = line->buf; -+ -+ /* alert dialog */ -+ if (strncmp(REPORT_PREFIX_ALERT, msg, alert_prefix_len) == 0) -+ { -+ msg += alert_prefix_len; -+ -+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), -+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, -+ GTK_MESSAGE_WARNING, -+ GTK_BUTTONS_CLOSE, -+ msg); -+ -+ gtk_dialog_run(GTK_DIALOG(dialog)); -+ gtk_widget_destroy(dialog); -+ } -+ /* ask dialog with textbox */ -+ else if (strncmp(REPORT_PREFIX_ASK, msg, ask_prefix_len) == 0) -+ { -+ msg += ask_prefix_len; -+ -+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), -+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, -+ GTK_MESSAGE_QUESTION, -+ GTK_BUTTONS_OK_CANCEL, -+ msg); -+ -+ GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); -+ GtkWidget *textbox = gtk_entry_new(); -+ gtk_entry_set_editable(GTK_ENTRY(textbox), TRUE); -+ gtk_box_pack_start(GTK_BOX(vbox), textbox, TRUE, TRUE, 0); -+ gtk_widget_show(textbox); -+ -+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) -+ { -+ const char *text = gtk_entry_get_text(GTK_ENTRY(textbox)); -+ char *response = xasprintf("%s\n", text); -+ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) -+ { -+ free(response); -+ VERB1 perror_msg("Unable to write %s\\n to child's stdin", text); -+ return FALSE; -+ } -+ -+ free(response); -+ } -+ else -+ { -+ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) -+ { -+ VERB1 perror_msg("Unable to write \\n to child's stdin"); -+ return FALSE; -+ } -+ } -+ -+ gtk_widget_destroy(textbox); -+ gtk_widget_destroy(dialog); -+ } -+ /* ask dialog with passwordbox */ -+ else if (strncmp(REPORT_PREFIX_ASK_PASSWORD, msg, ask_password_prefix_len) == 0) -+ { -+ msg += ask_password_prefix_len; -+ -+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), -+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, -+ GTK_MESSAGE_QUESTION, -+ GTK_BUTTONS_OK_CANCEL, -+ msg); -+ -+ GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); -+ GtkWidget *textbox = gtk_entry_new(); -+ gtk_entry_set_editable(GTK_ENTRY(textbox), TRUE); -+ gtk_entry_set_visibility(GTK_ENTRY(textbox), FALSE); -+ gtk_box_pack_start(GTK_BOX(vbox), textbox, TRUE, TRUE, 0); -+ gtk_widget_show(textbox); -+ -+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) -+ { -+ const char *text = gtk_entry_get_text(GTK_ENTRY(textbox)); -+ char *response = xasprintf("%s\n", text); -+ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) -+ { -+ free(response); -+ VERB1 perror_msg("Unable to write %s\\n to child's stdin", text); -+ return FALSE; -+ } -+ -+ free(response); -+ } -+ else -+ { -+ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) -+ { -+ VERB1 perror_msg("Unable to write \\n to child's stdin"); -+ return FALSE; -+ } -+ } -+ -+ gtk_widget_destroy(textbox); -+ gtk_widget_destroy(dialog); -+ } -+ /* yes/no dialog */ -+ else if (strncmp(REPORT_PREFIX_ASK_YES_NO, msg, ask_yes_no_prefix_len) == 0) -+ { -+ msg += ask_yes_no_prefix_len; -+ -+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_assistant), -+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, -+ GTK_MESSAGE_QUESTION, -+ GTK_BUTTONS_YES_NO, -+ msg); -+ -+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) -+ { -+ char *yes = _("y"); -+ char *response = xasprintf("%s\n", yes); -+ if (write(evd->run_state->command_in_fd, response, strlen(response)) < 0) -+ { -+ free(response); -+ VERB1 perror_msg("Unable to write %s\\n to child's stdin", yes); -+ return FALSE; -+ } -+ -+ free(response); -+ } -+ else -+ { -+ if (write(evd->run_state->command_in_fd, "\n", strlen("\n")) < 0) -+ { -+ VERB1 perror_msg("Unable to write \\n to child's stdin"); -+ return FALSE; -+ } -+ } -+ -+ gtk_widget_destroy(dialog); -+ } -+ /* no special prefix - forward to log */ -+ else -+ { -+ append_to_textview(evd->tv_log, msg); -+ save_to_event_log(evd, msg); -+ } -+ -+ strbuf_clear(line); -+ -+ /* jump to next line */ -+ raw = newline + 1; -+ } -+ -+ /* beginning of next line. the line continues by next read() */ -+ strbuf_append_str(line, raw); - } - -+ strbuf_free(line); -+ - if (r < 0 && errno == EAGAIN) - /* We got all buffered data, but fd is still open. Done for now */ - return TRUE; /* "please don't remove this event (yet)" */ -diff --git a/src/include/client.h b/src/include/client.h -index bbd2f10..8074145 100644 ---- a/src/include/client.h -+++ b/src/include/client.h -@@ -22,18 +22,25 @@ - - #define REPORT_PREFIX_ASK_YES_NO "ASK_YES_NO " - #define REPORT_PREFIX_ASK "ASK " -+#define REPORT_PREFIX_ASK_PASSWORD "ASK_PASSWORD " - #define REPORT_PREFIX_ALERT "ALERT " - - #ifdef __cplusplus - extern "C" { - #endif - -+#define set_echo libreport_set_echo -+int set_echo(int enable); -+ - #define ask_yes_no libreport_ask_yes_no - int ask_yes_no(const char *question); - - #define ask libreport_ask - char *ask(const char *question, char *response, int response_len); - -+#define ask_password libreport_ask_password -+char *ask_password(const char *question, char *response, int response_len); -+ - #define alert libreport_alert - void alert(const char *message); - -diff --git a/src/include/run_event.h b/src/include/run_event.h -index f7ae9ed..43730ce 100644 ---- a/src/include/run_event.h -+++ b/src/include/run_event.h -@@ -44,6 +44,7 @@ struct run_event_state { - GList *rule_list; - pid_t command_pid; - int command_out_fd; -+ int command_in_fd; - }; - struct run_event_state *new_run_event_state(void); - void free_run_event_state(struct run_event_state *state); -diff --git a/src/lib/client.c b/src/lib/client.c -index 88a995b..103828b 100644 ---- a/src/lib/client.c -+++ b/src/lib/client.c -@@ -25,6 +25,24 @@ static int is_slave_mode() - return getenv("REPORT_CLIENT_SLAVE") != NULL; - } - -+/* Returns 1 if echo has been changed from another state. */ -+int set_echo(int enable) -+{ -+ struct termios t; -+ if (tcgetattr(STDIN_FILENO, &t) < 0) -+ return 0; -+ -+ /* No change needed? */ -+ if ((t.c_lflag & ECHO) == enable) -+ return 0; -+ -+ t.c_lflag ^= ECHO; -+ if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) -+ perror_msg_and_die("tcsetattr"); -+ -+ return 1; -+} -+ - int ask_yes_no(const char *question) - { - const char *yes = _("y"); -@@ -32,12 +50,7 @@ int ask_yes_no(const char *question) - - char *env_response = getenv("REPORT_CLIENT_RESPONSE"); - if (env_response) -- { -- if (strncasecmp(yes, env_response, strlen(yes)) == 0) -- return true; -- if (strncasecmp(no, env_response, strlen(no)) == 0) -- return false; -- } -+ return strncasecmp(yes, env_response, strlen(yes)) == 0; - - if (is_slave_mode()) - printf(REPORT_PREFIX_ASK_YES_NO "%s\n", question); -@@ -48,7 +61,7 @@ int ask_yes_no(const char *question) - - char response[16]; - if (NULL == fgets(response, sizeof(response), stdin)) -- return false; -+ return 0; - - return strncasecmp(yes, response, strlen(yes)) == 0; - } -@@ -65,6 +78,22 @@ char *ask(const char *question, char *response, int response_len) - return fgets(response, response_len, stdin); - } - -+char *ask_password(const char *question, char *response, int response_len) -+{ -+ if (is_slave_mode()) -+ printf(REPORT_PREFIX_ASK_PASSWORD "%s\n", question); -+ else -+ printf("%s ", question); -+ -+ fflush(stdout); -+ -+ set_echo(false); -+ char *result = fgets(response, response_len, stdin); -+ set_echo(true); -+ -+ return result; -+} -+ - void alert(const char *message) - { - if (is_slave_mode()) -diff --git a/src/lib/run_event.c b/src/lib/run_event.c -index 0594bde..ba9920c 100644 ---- a/src/lib/run_event.c -+++ b/src/lib/run_event.c -@@ -18,6 +18,7 @@ - */ - #include - #include -+#include "client.h" - #include "internal_libreport.h" - - struct run_event_state *new_run_event_state() -@@ -393,7 +394,7 @@ 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]; -+ char *env_vec[4]; - /* 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... -@@ -402,7 +403,8 @@ int spawn_next_command(struct run_event_state *state, - env_vec[0] = xasprintf("DUMP_DIR=%s", (full_name ? full_name : dump_dir_name)); - free(full_name); - env_vec[1] = xasprintf("EVENT=%s", event); -- env_vec[2] = NULL; -+ env_vec[2] = xasprintf("REPORT_CLIENT_SLAVE=1"); -+ env_vec[3] = NULL; - - char *argv[4]; - argv[0] = (char*)"/bin/sh"; // TODO: honor $SHELL? -@@ -412,7 +414,7 @@ int spawn_next_command(struct run_event_state *state, - - int pipefds[2]; - state->command_pid = fork_execv_on_steroids( -- EXECFLG_INPUT_NUL + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, -+ EXECFLG_INPUT + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, - argv, - pipefds, - /* env_vec: */ env_vec, -@@ -420,9 +422,11 @@ int spawn_next_command(struct run_event_state *state, - /* uid(unused): */ 0 - ); - state->command_out_fd = pipefds[0]; -+ state->command_in_fd = pipefds[1]; - - free(env_vec[0]); - free(env_vec[1]); -+ free(env_vec[2]); - free(cmd); - - return 0; -@@ -447,10 +451,68 @@ int run_event_on_dir_name(struct run_event_state *state, - if (!fp) - die_out_of_memory(); - char *buf; -+ char *msg; -+ -+ int alert_prefix_len = strlen(REPORT_PREFIX_ALERT); -+ int ask_prefix_len = strlen(REPORT_PREFIX_ASK); -+ int ask_yes_no_prefix_len = strlen(REPORT_PREFIX_ASK_YES_NO); -+ int ask_password_prefix_len = strlen(REPORT_PREFIX_ASK_PASSWORD); -+ - while ((buf = xmalloc_fgetline(fp)) != NULL) - { -- if (state->logging_callback) -- buf = state->logging_callback(buf, state->logging_param); -+ msg = buf; -+ -+ /* just cut off prefix, no waiting */ -+ if (strncmp(REPORT_PREFIX_ALERT, msg, alert_prefix_len) == 0) -+ { -+ msg += alert_prefix_len; -+ printf("%s\n", msg); -+ fflush(stdout); -+ } -+ /* wait for y/N response on the same line */ -+ else if (strncmp(REPORT_PREFIX_ASK_YES_NO, msg, ask_yes_no_prefix_len) == 0) -+ { -+ msg += ask_yes_no_prefix_len; -+ printf("%s [%s/%s] ", msg, _("y"), _("N")); -+ fflush(stdout); -+ char buf[16]; -+ if (!fgets(buf, sizeof(buf), stdin)) -+ buf[0] = '\0'; -+ -+ if (write(state->command_in_fd, buf, strlen(buf)) < 0) -+ perror_msg_and_die("write"); -+ } -+ /* wait for the string on the same line */ -+ else if (strncmp(REPORT_PREFIX_ASK, msg, ask_prefix_len) == 0) -+ { -+ msg += ask_prefix_len; -+ printf("%s ", msg); -+ fflush(stdout); -+ char buf[256]; -+ if (!fgets(buf, sizeof(buf), stdin)) -+ buf[0] = '\0'; -+ -+ if (write(state->command_in_fd, buf, strlen(buf)) < 0) -+ perror_msg_and_die("write"); -+ } -+ /* set echo off and wait for password on the same line */ -+ else if (strncmp(REPORT_PREFIX_ASK_PASSWORD, msg, ask_password_prefix_len) == 0) -+ { -+ msg += ask_password_prefix_len; -+ printf("%s ", msg); -+ fflush(stdout); -+ char buf[256]; -+ set_echo(false); -+ if (!fgets(buf, sizeof(buf), stdin)) -+ buf[0] = '\0'; -+ set_echo(true); -+ -+ if (write(state->command_in_fd, buf, strlen(buf)) < 0) -+ perror_msg_and_die("write"); -+ } -+ /* no special prefix -> forward to log if applicable */ -+ else if (state->logging_callback) -+ msg = state->logging_callback(msg, state->logging_param); - free(buf); - } - fclose(fp); /* Got EOF, close. This also closes state->command_out_fd */ diff --git a/libreport.spec b/libreport.spec index ef2ae50..701fe02 100644 --- a/libreport.spec +++ b/libreport.spec @@ -5,12 +5,23 @@ Summary: Generic library for reporting various problems Name: libreport Version: 2.0.5 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2+ Group: System Environment/Libraries URL: https://fedorahosted.org/abrt/ Source: https://fedorahosted.org/released/abrt/%{name}-%{version}.tar.gz -Patch0: interactive-libreport.patch +Patch0: 0001-fix-el6-keyring.patch +Patch1: 0002-Add-a-button-to-add-more-files-to-dump-dir.-Closes-1.patch +Patch2: 0003-Ignore-files-which-seem-to-be-editor-backups.-Closes.patch +Patch3: 0004-wizard-steal-directory-before-copying-added-files-to.patch +Patch4: 0005-wizard.glade-glade-generates-class-GtkBox-which-does.patch +Patch5: 0006-support-interactive-plugins-in-GUI-and-CLI.patch +Patch6: 0007-wizard-if-more-than-one-reporter-is-chosen-select-al.patch +Patch7: 0008-added-xml-file-for-Logger-event.patch +Patch8: 0009-report-cli-don-t-crash-when-invalid-analyzer-is-sele.patch +Patch9: 0010-Add-another-reporting-flag-LIBREPORT_GETPID.patch +Patch10: 0011-add-python-bindings-for-interactive-plugins.patch +Patch11: 0012-run_event_on_dir-fix-double-free.patch BuildRequires: dbus-devel BuildRequires: gtk2-devel BuildRequires: curl-devel @@ -59,8 +70,8 @@ Summary: Python bindings for report-libs # Is group correct here? - Group: System Environment/Libraries Requires: libreport = %{version}-%{release} -Provides: report = 0.22-1 -Obsoletes: report < 0.22-1 +Provides: report = 0.23-1 +Obsoletes: report < 0.23-1 # in report the rhtsupport is in the main package, so we need to install it too %if 0%{?rhel} >= 6 Requires: libreport-plugin-rhtsupport @@ -82,8 +93,8 @@ with problem dump reports Summary: %{name}'s newt interface Group: User Interface/Desktops Requires: %{name} = %{version}-%{release} -Provides: report-newt = 0.22-1 -Obsoletes: report-newt < 0.22-1 +Provides: report-newt = 0.23-1 +Obsoletes: report-newt < 0.23-1 %description newt This package contains a simple newt application for reporting @@ -93,8 +104,8 @@ bugs Summary: GTK front-end for libreport Group: User Interface/Desktops Requires: libreport = %{version}-%{release} -Provides: report-gtk = 0.22-1 -Obsoletes: report-gtk < 0.22-1 +Provides: report-gtk = 0.23-1 +Obsoletes: report-gtk < 0.23-1 %description gtk Applications for reporting bugs using libreport backend @@ -122,10 +133,10 @@ Summary: %{name}'s logger reporter plugin Group: System Environment/Libraries Requires: %{name} = %{version}-%{release} Obsoletes: abrt-plugin-logger < 2.0.4 -Provides: report-plugin-localsave = 0.22-1 -Obsoletes: report-plugin-localsave < 0.22-1 -Provides: report-config-localsave = 0.22-1 -Obsoletes: report-config-localsave < 0.22-1 +Provides: report-plugin-localsave = 0.23-1 +Obsoletes: report-plugin-localsave < 0.23-1 +Provides: report-config-localsave = 0.23-1 +Obsoletes: report-config-localsave < 0.23-1 %description plugin-logger The simple reporter plugin which writes a report to a specified file. @@ -146,10 +157,10 @@ Summary: %{name}'s bugzilla plugin Group: System Environment/Libraries Requires: %{name} = %{version}-%{release} Obsoletes: abrt-plugin-bugzilla < 2.0.4 -Provides: report-plugin-bugzilla = 0.22-1 -Obsoletes: report-plugin-bugzilla < 0.22-1 -Provides: report-config-bugzilla-redhat-com = 0.22-1 -Obsoletes: report-config-bugzilla-redhat-com < 0.22-1 +Provides: report-plugin-bugzilla = 0.23-1 +Obsoletes: report-plugin-bugzilla < 0.23-1 +Provides: report-config-bugzilla-redhat-com = 0.23-1 +Obsoletes: report-config-bugzilla-redhat-com < 0.23-1 %description plugin-bugzilla Plugin to report bugs into the bugzilla. @@ -168,24 +179,38 @@ Summary: %{name}'s reportuploader plugin Group: System Environment/Libraries Requires: %{name} = %{version}-%{release} Obsoletes: abrt-plugin-reportuploader < 2.0.4 -Provides: report-plugin-ftp = 0.22-1 -Obsoletes: report-plugin-ftp < 0.22-1 -Provides: report-config-ftp = 0.22-1 -Obsoletes: report-config-ftp < 0.22-1 -Provides: report-plugin-scp = 0.22-1 -Obsoletes: report-plugin-scp < 0.22-1 -Provides: report-config-scp = 0.22-1 -Obsoletes: report-config-scp < 0.22-1 +Provides: report-plugin-ftp = 0.23-1 +Obsoletes: report-plugin-ftp < 0.23-1 +Provides: report-config-ftp = 0.23-1 +Obsoletes: report-config-ftp < 0.23-1 +Provides: report-plugin-scp = 0.23-1 +Obsoletes: report-plugin-scp < 0.23-1 +Provides: report-config-scp = 0.23-1 +Obsoletes: report-config-scp < 0.23-1 %description plugin-reportuploader Plugin to report bugs into anonymous FTP site associated with ticketing system. %prep %setup -q -%patch0 -p1 -b .interactive +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 %build +mkdir -p m4 +test -r m4/aclocal.m4 || touch m4/aclocal.m4 autoconf +automake %configure sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool @@ -260,6 +285,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %files python %defattr(-,root,root,-) %{python_sitearch}/report/* +%{python_sitearch}/reportclient/* %files cli %defattr(-,root,root,-) @@ -290,6 +316,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %files plugin-logger %defattr(-,root,root,-) %{_sysconfdir}/libreport/events/report_Logger.conf +%{_sysconfdir}/libreport/events/report_Logger.xml %config(noreplace) %{_sysconfdir}/libreport/events.d/print_event.conf %{_bindir}/reporter-print %{_mandir}/man*/reporter-print.* @@ -323,6 +350,16 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_bindir}/reporter-upload %changelog +* Thu Jul 21 2011 Jiri Moskovcak 2.0.5-2 +- obsolete report in rawhide properly rhbz#723320 +- added button to add attachments +- ignore backup files +- improved support for interactive plugins +- added description text for logger +- added python bindings for interactive plugins +- Resolves: #723320 + + * Mon Jul 18 2011 Jiri Moskovcak 2.0.5-1 - move reporter plugins from abrt to libreport - fixed provides/obsolete to properly obsolete report package diff --git a/remove_pyreport.patch b/remove_pyreport.patch deleted file mode 100644 index 0bfeed1..0000000 --- a/remove_pyreport.patch +++ /dev/null @@ -1,6 +0,0 @@ -diff -urp libreport-2.0.2/src/Makefile.am libreport-2.0.2_/src/Makefile.am ---- libreport-2.0.2/src/Makefile.am 2011-06-08 17:15:03.000000000 +0200 -+++ libreport-2.0.2_/src/Makefile.am 2011-06-09 11:31:01.494126920 +0200 -@@ -1 +1 @@ --SUBDIRS = include lib report-python gtk-helpers gui-wizard-gtk cli -+SUBDIRS = include lib gtk-helpers gui-wizard-gtk cli