From 9e8a1ba0c9ddfa0108050f6fedc88de63b4b7c3f Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 15:54:05 +0200 Subject: Initial implementation of crash report editor. Splitted CLI.cpp into multiple files for clarity. --- src/CLI/report.cpp | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 src/CLI/report.cpp (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp new file mode 100644 index 0000000..6f2ba6a --- /dev/null +++ b/src/CLI/report.cpp @@ -0,0 +1,344 @@ +/* + 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 "report.h" +#include "run-command.h" +#include "dbus.h" +#include "abrtlib.h" +#if HAVE_CONFIG_H +#include +#endif +#if ENABLE_NLS +#include +#define _(S) gettext(S) +#else +#define _(S) (S) +#endif + +#define FIELD_SEP "%----" + +/* Escapes the field content string to avoid confusion with file comments. + Returned field must be free()d by caller. */ +static char *escape(const char *str) +{ + // Determine the size of resultant string. + // Count the required number of escape characters. + // 1. NEWLINE followed by # + // 2. NEWLINE followed by \# (escaped version) + const char *ptr = str; + bool newline = true; + int count = 0; + while (*ptr) + { + if (newline) + { + if (*ptr == '#') + ++count; + if (*ptr == '\\' && *(ptr + 1) == '#') + ++count; + } + + newline = (*ptr == '\n'); + ++ptr; + } + + // Copy the input string to the resultant string, and escape all + // occurences of \# and #. + char *result = (char*)malloc(strlen(str) + 1 + count); + if (!result) + error_msg_and_die("Memory error while escaping a field."); + + const char *src = str; + char *dest = result; + newline = true; + while (*src) + { + if (newline) + { + if (*src == '#') + *dest++ = '\\'; + else if (*src == '\\' && *(src + 1) == '#') + *dest++ = '\\'; + } + + newline = (*src == '\n'); + *dest++ = *src++; + } + *dest = '\0'; + return result; +} + +/* Removes all comment lines, and unescapes the string previously escaped + by escape(). Works in-place. */ +static char *remove_comments_and_unescape(char *str) +{ + char *src = str, *dest = str; + bool newline = true; + while (*src) + { + if (newline) + { + if (*src == '#') + { // Skip the comment line! + while (*src && *src != '\n') + ++src; + + if (*src == '\0') + break; + + ++src; + continue; + } + else if (*src == '\\' && + (*(src + 1) == '#' || + (*(src + 1) == '\\' && *(src + 2) == '#'))) + { + ++src; // Unescape escaped char. + } + } + + newline = (*src == '\n'); + *dest++ = *src++; + } + *dest = '\0'; +} + +/* Writes a field of crash report to a file. + * Field must be writable. + */ +static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, + const char *field, const char *description) +{ + const map_crash_report_t::const_iterator it = report.find(field); + if (it == report.end()) + { + error_msg("Field %s not found.\n", field); + return; + } + + if (it->second[CD_TYPE] == CD_SYS) + { + error_msg("Cannot write field %s because it is a system value\n", field); + return; + } + + fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str()); + + bool readonly = (it->second[CD_EDITABLE] != CD_ISEDITABLE); + fprintf(fp, readonly ? _("# %s (read only)\n") : "# %s\n", description); + + char *escaped_content = escape(it->second[CD_CONTENT].c_str()); + fprintf(fp, "%s\n", escaped_content); + free(escaped_content); +} + +/* Saves the crash report to a file. + * Fp must be opened before write_crash_report is called. + * Returned Value: + * If the report is successfully stored to the file, a zero value is returned. + * On failure, nonzero value is returned. + */ +static int write_crash_report(const map_crash_report_t &report, FILE *fp) +{ + fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" + "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); + + write_crash_report_field(fp, report, "Comment", + _("Describe the circumstances of this crash below.")); + write_crash_report_field(fp, report, "How to reproduce", + _("How to reproduce the crash?")); + write_crash_report_field(fp, report, "backtrace", + _("Backtrace. Check that it does not contain any sensitive data such as passwords.")); + write_crash_report_field(fp, report, "UUID", "UUID"); + write_crash_report_field(fp, report, "architecture", "Architecture"); + write_crash_report_field(fp, report, "cmdline", "Command line"); + write_crash_report_field(fp, report, "component", "Component"); + write_crash_report_field(fp, report, "coredump", "Core dump"); + write_crash_report_field(fp, report, "executable", "Executable"); + write_crash_report_field(fp, report, "kernel", "Kernel"); + write_crash_report_field(fp, report, "package", "Package"); + write_crash_report_field(fp, report, "reason", "Reason"); + write_crash_report_field(fp, report, "release", "Release"); + + return 0; +} + +/* + * Updates appropriate field in the report from the text. The text can + * contain multiple fields. + */ +static void read_crash_report_field(const char *text, map_crash_report_t &report, + const char *field) +{ + char separator[strlen("\n" FIELD_SEP) + strlen(field) + 2]; // 2 = '\n\0' + sprintf(separator, "\n%s%s\n", FIELD_SEP, field); + const char *textfield = strstr(text, separator); + if (!textfield) + return; + + textfield += strlen(separator); + int length = 0; + const char *end = strstr(textfield, "\n" FIELD_SEP); + if (!end) + length = strlen(textfield); + else + length = end - textfield; + + const map_crash_report_t::iterator it = report.find(field); + if (it == report.end()) + { + error_msg("Field %s not found.\n", field); + return; + } + + if (it->second[CD_TYPE] == CD_SYS) + { + error_msg("Cannot update field %s because it is a system value.\n", field); + return; + } + + if (it->second[CD_EDITABLE] == CD_ISEDITABLE) + it->second[CD_CONTENT].assign(textfield, length); +} + +/* + * Updates the crash report 'report' from the text. The text must not contain + * any comments. + */ +static int read_crash_report(map_crash_report_t &report, const char *text) +{ + read_crash_report_field(text, report, "Comment"); + read_crash_report_field(text, report, "How to reproduce"); + read_crash_report_field(text, report, "backtrace"); + read_crash_report_field(text, report, "UUID"); + read_crash_report_field(text, report, "architecture"); + read_crash_report_field(text, report, "cmdline"); + read_crash_report_field(text, report, "component"); + read_crash_report_field(text, report, "coredump"); + read_crash_report_field(text, report, "executable"); + read_crash_report_field(text, report, "kernel"); + read_crash_report_field(text, report, "package"); + read_crash_report_field(text, report, "reason"); + read_crash_report_field(text, report, "release"); + + return 0; +} + +/* Runs external editor. */ +int launch_editor(const char *path) +{ + const char *editor, *terminal; + + editor = getenv("ABRT_EDITOR"); + if (!editor) + editor = getenv("VISUAL"); + if (!editor) + editor = getenv("EDITOR"); + + terminal = getenv("TERM"); + if (!editor && (!terminal || !strcmp(terminal, "dumb"))) + { + error_msg(_("Terminal is dumb but no VISUAL nor EDITOR defined.")); + return 1; + } + + if (!editor) + editor = "vi"; + + const char *args[6]; + args[0] = editor; + args[1] = path; + run_command(args); + + return 0; +} + +/* Reports the crash with corresponding uuid over DBus. */ +int report(const char *uuid, bool always) +{ + map_crash_report_t cr = call_CreateReport(uuid); + + if (always) + { + call_Report(cr); + return 0; + } + + /* Open a temporary file and write the crash report to it. */ + char filename[] = "/tmp/abrt-report.XXXXXX"; + int fd = mkstemp(filename); + if (fd == -1) + { + error_msg("could not generate temporary file name"); + return 1; + } + + FILE *fp = fdopen(fd, "w"); + if (!fp) + { + error_msg("could not open '%s' to save the crash report", filename); + return 1; + } + + write_crash_report(cr, fp); + + if (fclose(fp)) + { + error_msg("could not close '%s'", filename); + return 2; + } + + launch_editor(filename); + + fp = fopen(filename, "r"); + if (!fp) + { + error_msg("could not open '%s' to read the crash report", filename); + return 1; + } + + fseek(fp, 0, SEEK_END); + long size = ftell(fp); + printf("%d", size); + fseek(fp, 0, SEEK_SET); + + char *text = (char*)malloc(size + 1); + if (fread(text, 1, size, fp) != size) + { + error_msg("could not read '%s'", filename); + return 1; + } + text[size] = '\0'; + fclose(fp); + + remove_comments_and_unescape(text); + read_crash_report(cr, text); + free(text); + + /*int result = */unlink(filename); + + printf(_("\nReport has been updated.\nDo you want to send the report? [y/n]: ")); + fflush(NULL); + char answer[16] = "n"; + fgets(answer, sizeof(answer), stdin); + if (answer[0] == 'Y' || answer[0] == 'y') + { + call_Report(cr); + } + + return 0; +} -- cgit From f16349195d117198603d6c951b7af434afda2339 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 16:45:15 +0200 Subject: Code comments. Better UI texts. --- src/CLI/report.cpp | 58 +++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 6f2ba6a..57dc625 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -29,10 +29,13 @@ #define _(S) (S) #endif +/* Field separator for the crash report file that is edited by user. */ #define FIELD_SEP "%----" -/* Escapes the field content string to avoid confusion with file comments. - Returned field must be free()d by caller. */ +/* + * Escapes the field content string to avoid confusion with file comments. + * Returned field must be free()d by caller. + */ static char *escape(const char *str) { // Determine the size of resultant string. @@ -82,8 +85,10 @@ static char *escape(const char *str) return result; } -/* Removes all comment lines, and unescapes the string previously escaped - by escape(). Works in-place. */ +/* + * Removes all comment lines, and unescapes the string previously escaped + * by escape(). Works in-place. + */ static char *remove_comments_and_unescape(char *str) { char *src = str, *dest = str; @@ -138,17 +143,19 @@ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str()); - bool readonly = (it->second[CD_EDITABLE] != CD_ISEDITABLE); - fprintf(fp, readonly ? _("# %s (read only)\n") : "# %s\n", description); + fprintf(fp, "%s\n", description); + if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + fprintf(fp, _("# This field is read only.\n")); char *escaped_content = escape(it->second[CD_CONTENT].c_str()); fprintf(fp, "%s\n", escaped_content); free(escaped_content); } -/* Saves the crash report to a file. - * Fp must be opened before write_crash_report is called. - * Returned Value: +/* + * Saves the crash report to a file. + * Parameter 'fp' must be opened before write_crash_report is called. + * Returned value: * If the report is successfully stored to the file, a zero value is returned. * On failure, nonzero value is returned. */ @@ -158,22 +165,22 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp) "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); write_crash_report_field(fp, report, "Comment", - _("Describe the circumstances of this crash below.")); + _("# Describe the circumstances of this crash below.")); write_crash_report_field(fp, report, "How to reproduce", - _("How to reproduce the crash?")); + _("# How to reproduce the crash?")); write_crash_report_field(fp, report, "backtrace", - _("Backtrace. Check that it does not contain any sensitive data such as passwords.")); - write_crash_report_field(fp, report, "UUID", "UUID"); - write_crash_report_field(fp, report, "architecture", "Architecture"); - write_crash_report_field(fp, report, "cmdline", "Command line"); - write_crash_report_field(fp, report, "component", "Component"); - write_crash_report_field(fp, report, "coredump", "Core dump"); - write_crash_report_field(fp, report, "executable", "Executable"); - write_crash_report_field(fp, report, "kernel", "Kernel"); - write_crash_report_field(fp, report, "package", "Package"); - write_crash_report_field(fp, report, "reason", "Reason"); - write_crash_report_field(fp, report, "release", "Release"); - + _("# Stack trace: a list of active stack frames at the time the crash occurred\n# Check that it does not contain any sensitive data such as passwords.")); + write_crash_report_field(fp, report, "UUID", _("# UUID")); + write_crash_report_field(fp, report, "architecture", _("# Architecture")); + write_crash_report_field(fp, report, "cmdline", _("# Command line")); + write_crash_report_field(fp, report, "component", _("# Component")); + write_crash_report_field(fp, report, "coredump", _("# Core dump")); + write_crash_report_field(fp, report, "executable", _("# Executable")); + write_crash_report_field(fp, report, "kernel", _("# Kernel version")); + write_crash_report_field(fp, report, "package", _("# Package")); + write_crash_report_field(fp, report, "reason", _("# Reason of crash")); + write_crash_report_field(fp, report, "release", _("# Release string of the operating system")); + return 0; } @@ -313,7 +320,6 @@ int report(const char *uuid, bool always) fseek(fp, 0, SEEK_END); long size = ftell(fp); - printf("%d", size); fseek(fp, 0, SEEK_SET); char *text = (char*)malloc(size + 1); @@ -331,14 +337,12 @@ int report(const char *uuid, bool always) /*int result = */unlink(filename); - printf(_("\nReport has been updated.\nDo you want to send the report? [y/n]: ")); + printf(_("\nThe report has been updated.\nDo you want to send the report? [y/N]: ")); fflush(NULL); char answer[16] = "n"; fgets(answer, sizeof(answer), stdin); if (answer[0] == 'Y' || answer[0] == 'y') - { call_Report(cr); - } return 0; } -- cgit From 8ea7097910579362f994ceaf17b9d256ce894826 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 16:49:10 +0200 Subject: Print error on unlink failure. --- src/CLI/report.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 57dc625..e1a0cd2 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -335,7 +335,8 @@ int report(const char *uuid, bool always) read_crash_report(cr, text); free(text); - /*int result = */unlink(filename); + if (unlink(filename) != 0) + error_msg("could not unlink %s: %s", filename, strerror(errno)); printf(_("\nThe report has been updated.\nDo you want to send the report? [y/N]: ")); fflush(NULL); -- cgit From c88b42d31d786dddf4dda5a4beb6bc34a405fecc Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 17:11:08 +0200 Subject: More comments. --- src/CLI/report.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index e1a0cd2..88cb1ce 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -122,7 +122,8 @@ static char *remove_comments_and_unescape(char *str) *dest = '\0'; } -/* Writes a field of crash report to a file. +/* + * Writes a field of crash report to a file. * Field must be writable. */ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, @@ -277,10 +278,12 @@ int launch_editor(const char *path) /* Reports the crash with corresponding uuid over DBus. */ int report(const char *uuid, bool always) { + // Ask for an initial report. map_crash_report_t cr = call_CreateReport(uuid); if (always) { + // Send the report immediately. call_Report(cr); return 0; } @@ -308,9 +311,11 @@ int report(const char *uuid, bool always) error_msg("could not close '%s'", filename); return 2; } - + + // Start a text editor on the temporary file. launch_editor(filename); + // Read the file back and update the report from the file. fp = fopen(filename, "r"); if (!fp) { @@ -332,12 +337,13 @@ int report(const char *uuid, bool always) fclose(fp); remove_comments_and_unescape(text); - read_crash_report(cr, text); + read_crash_report(cr, text); // Updates the crash report from the file text. free(text); - if (unlink(filename) != 0) + if (unlink(filename) != 0) // Delete the tempfile. error_msg("could not unlink %s: %s", filename, strerror(errno)); + // Report only if the user is sure. printf(_("\nThe report has been updated.\nDo you want to send the report? [y/N]: ")); fflush(NULL); char answer[16] = "n"; -- cgit From e1a887790d3e98f695f9f88e4d12dd675c7211b9 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 17:47:59 +0200 Subject: Inform whether some changes were detected in the crash report. --- src/CLI/report.cpp | 108 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 24 deletions(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 88cb1ce..5506532 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -32,6 +32,33 @@ /* Field separator for the crash report file that is edited by user. */ #define FIELD_SEP "%----" +/* + * Trims whitespace characters both from left and right side of a string. + * Modifies the string in-place. Returns the trimmed string. + */ +char *trim(char *str) +{ + if (!str) + return NULL; + + // Remove leading spaces. + char *ibuf; + for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf) + ; + if (str != ibuf) + memmove(str, ibuf, ibuf - str); + + // Remove trailing spaces. + int i = strlen(str); + while (--i >= 0) + { + if (!isspace(str[i])) + break; + } + str[++i] = NULL; + return str; +} + /* * Escapes the field content string to avoid confusion with file comments. * Returned field must be free()d by caller. @@ -188,15 +215,19 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp) /* * Updates appropriate field in the report from the text. The text can * contain multiple fields. + * Returns: + * 0 if no change to the field was detected. + * 1 if the field was changed. + * Changes to read-only fields are ignored. */ -static void read_crash_report_field(const char *text, map_crash_report_t &report, - const char *field) +static int read_crash_report_field(const char *text, map_crash_report_t &report, + const char *field) { char separator[strlen("\n" FIELD_SEP) + strlen(field) + 2]; // 2 = '\n\0' sprintf(separator, "\n%s%s\n", FIELD_SEP, field); const char *textfield = strstr(text, separator); if (!textfield) - return; + return 0; textfield += strlen(separator); int length = 0; @@ -210,40 +241,63 @@ static void read_crash_report_field(const char *text, map_crash_report_t &report if (it == report.end()) { error_msg("Field %s not found.\n", field); - return; + return 0; } if (it->second[CD_TYPE] == CD_SYS) { error_msg("Cannot update field %s because it is a system value.\n", field); - return; + return 0; } - if (it->second[CD_EDITABLE] == CD_ISEDITABLE) - it->second[CD_CONTENT].assign(textfield, length); + // Do not change noneditable fields. + if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + return 0; + + // Compare the old field contents with the new field contents. + char newvalue[length + 1]; + strncpy(newvalue, textfield, length); + newvalue[length] = '\0'; + trim(newvalue); + + char oldvalue[it->second[CD_CONTENT].length() + 1]; + strcpy(oldvalue, it->second[CD_CONTENT].c_str()); + trim(oldvalue); + + // Return if no change in the contents detected. + int cmp = strcmp(newvalue, oldvalue); + if (!cmp) + return 0; + + it->second[CD_CONTENT].assign(newvalue); + return 1; } /* * Updates the crash report 'report' from the text. The text must not contain * any comments. + * Returns: + * 0 if no field was changed. + * 1 if any field was changed. + * Changes to read-only fields are ignored. */ static int read_crash_report(map_crash_report_t &report, const char *text) { - read_crash_report_field(text, report, "Comment"); - read_crash_report_field(text, report, "How to reproduce"); - read_crash_report_field(text, report, "backtrace"); - read_crash_report_field(text, report, "UUID"); - read_crash_report_field(text, report, "architecture"); - read_crash_report_field(text, report, "cmdline"); - read_crash_report_field(text, report, "component"); - read_crash_report_field(text, report, "coredump"); - read_crash_report_field(text, report, "executable"); - read_crash_report_field(text, report, "kernel"); - read_crash_report_field(text, report, "package"); - read_crash_report_field(text, report, "reason"); - read_crash_report_field(text, report, "release"); - - return 0; + int result = 0; + result |= read_crash_report_field(text, report, "Comment"); + result |= read_crash_report_field(text, report, "How to reproduce"); + result |= read_crash_report_field(text, report, "backtrace"); + result |= read_crash_report_field(text, report, "UUID"); + result |= read_crash_report_field(text, report, "architecture"); + result |= read_crash_report_field(text, report, "cmdline"); + result |= read_crash_report_field(text, report, "component"); + result |= read_crash_report_field(text, report, "coredump"); + result |= read_crash_report_field(text, report, "executable"); + result |= read_crash_report_field(text, report, "kernel"); + result |= read_crash_report_field(text, report, "package"); + result |= read_crash_report_field(text, report, "reason"); + result |= read_crash_report_field(text, report, "release"); + return result; } /* Runs external editor. */ @@ -337,14 +391,20 @@ int report(const char *uuid, bool always) fclose(fp); remove_comments_and_unescape(text); - read_crash_report(cr, text); // Updates the crash report from the file text. + // Updates the crash report from the file text. + int report_changed = read_crash_report(cr, text); + if (report_changed) + puts(_("\nThe report has been updated.")); + else + puts(_("\nNo changes were detected in the report.")); + free(text); if (unlink(filename) != 0) // Delete the tempfile. error_msg("could not unlink %s: %s", filename, strerror(errno)); // Report only if the user is sure. - printf(_("\nThe report has been updated.\nDo you want to send the report? [y/N]: ")); + printf(_("Do you want to send the report? [y/N]: ")); fflush(NULL); char answer[16] = "n"; fgets(answer, sizeof(answer), stdin); -- cgit From 908ba185ac9651945f4c4c4f8fb5155875cd246c Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 20 Oct 2009 17:54:53 +0200 Subject: Tell user about sending the report. --- src/CLI/report.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 5506532..b9c6d41 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -409,7 +409,13 @@ int report(const char *uuid, bool always) char answer[16] = "n"; fgets(answer, sizeof(answer), stdin); if (answer[0] == 'Y' || answer[0] == 'y') + { + puts(_("Reporting...")); call_Report(cr); + puts(_("Crash report was successfully sent.")); + } + else + puts(_("Crash report was not sent.")); return 0; } -- cgit From c5cbf4ac39edb168810eb94a55c3282aa30b0620 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Wed, 21 Oct 2009 14:55:32 +0200 Subject: Use defines instead of strings where possible. --- src/CLI/report.cpp | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index b9c6d41..8dedf03 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -19,6 +19,7 @@ #include "run-command.h" #include "dbus.h" #include "abrtlib.h" +#include "DebugDump.h" // FILENAME_* defines #if HAVE_CONFIG_H #include #endif @@ -159,7 +160,8 @@ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, const map_crash_report_t::const_iterator it = report.find(field); if (it == report.end()) { - error_msg("Field %s not found.\n", field); + // exit silently, all fields are optional for now + //error_msg("Field %s not found.\n", field); return; } @@ -192,22 +194,22 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp) fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); - write_crash_report_field(fp, report, "Comment", + write_crash_report_field(fp, report, CD_COMMENT, _("# Describe the circumstances of this crash below.")); - write_crash_report_field(fp, report, "How to reproduce", + write_crash_report_field(fp, report, CD_REPRODUCE, _("# How to reproduce the crash?")); write_crash_report_field(fp, report, "backtrace", _("# Stack trace: a list of active stack frames at the time the crash occurred\n# Check that it does not contain any sensitive data such as passwords.")); - write_crash_report_field(fp, report, "UUID", _("# UUID")); - write_crash_report_field(fp, report, "architecture", _("# Architecture")); + write_crash_report_field(fp, report, CD_UUID, _("# UUID")); + write_crash_report_field(fp, report, FILENAME_ARCHITECTURE, _("# Architecture")); write_crash_report_field(fp, report, "cmdline", _("# Command line")); - write_crash_report_field(fp, report, "component", _("# Component")); + write_crash_report_field(fp, report, FILENAME_COMPONENT, _("# Component")); write_crash_report_field(fp, report, "coredump", _("# Core dump")); - write_crash_report_field(fp, report, "executable", _("# Executable")); - write_crash_report_field(fp, report, "kernel", _("# Kernel version")); - write_crash_report_field(fp, report, "package", _("# Package")); - write_crash_report_field(fp, report, "reason", _("# Reason of crash")); - write_crash_report_field(fp, report, "release", _("# Release string of the operating system")); + write_crash_report_field(fp, report, FILENAME_EXECUTABLE, _("# Executable")); + write_crash_report_field(fp, report, FILENAME_KERNEL, _("# Kernel version")); + write_crash_report_field(fp, report, FILENAME_PACKAGE, _("# Package")); + write_crash_report_field(fp, report, FILENAME_REASON, _("# Reason of crash")); + write_crash_report_field(fp, report, FILENAME_RELEASE, _("# Release string of the operating system")); return 0; } @@ -227,7 +229,7 @@ static int read_crash_report_field(const char *text, map_crash_report_t &report, sprintf(separator, "\n%s%s\n", FIELD_SEP, field); const char *textfield = strstr(text, separator); if (!textfield) - return 0; + return 0; // exit silently because all fields are optional textfield += strlen(separator); int length = 0; @@ -284,19 +286,19 @@ static int read_crash_report_field(const char *text, map_crash_report_t &report, static int read_crash_report(map_crash_report_t &report, const char *text) { int result = 0; - result |= read_crash_report_field(text, report, "Comment"); - result |= read_crash_report_field(text, report, "How to reproduce"); + result |= read_crash_report_field(text, report, CD_COMMENT); + result |= read_crash_report_field(text, report, CD_REPRODUCE); result |= read_crash_report_field(text, report, "backtrace"); - result |= read_crash_report_field(text, report, "UUID"); - result |= read_crash_report_field(text, report, "architecture"); + result |= read_crash_report_field(text, report, CD_UUID); + result |= read_crash_report_field(text, report, FILENAME_ARCHITECTURE); result |= read_crash_report_field(text, report, "cmdline"); - result |= read_crash_report_field(text, report, "component"); + result |= read_crash_report_field(text, report, FILENAME_COMPONENT); result |= read_crash_report_field(text, report, "coredump"); - result |= read_crash_report_field(text, report, "executable"); - result |= read_crash_report_field(text, report, "kernel"); - result |= read_crash_report_field(text, report, "package"); - result |= read_crash_report_field(text, report, "reason"); - result |= read_crash_report_field(text, report, "release"); + result |= read_crash_report_field(text, report, FILENAME_EXECUTABLE); + result |= read_crash_report_field(text, report, FILENAME_KERNEL); + result |= read_crash_report_field(text, report, FILENAME_PACKAGE); + result |= read_crash_report_field(text, report, FILENAME_REASON); + result |= read_crash_report_field(text, report, FILENAME_RELEASE); return result; } -- cgit From f824969d3a8e77a41dac30997b47a0268cc01cbd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 21 Oct 2009 15:49:01 +0200 Subject: fix warning and whitespace damage Signed-off-by: Denys Vlasenko --- src/CLI/report.cpp | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'src/CLI/report.cpp') diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 8dedf03..b9a1391 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -33,15 +33,15 @@ /* Field separator for the crash report file that is edited by user. */ #define FIELD_SEP "%----" -/* - * Trims whitespace characters both from left and right side of a string. +/* + * Trims whitespace characters both from left and right side of a string. * Modifies the string in-place. Returns the trimmed string. */ char *trim(char *str) { if (!str) return NULL; - + // Remove leading spaces. char *ibuf; for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf) @@ -60,9 +60,9 @@ char *trim(char *str) return str; } -/* - * Escapes the field content string to avoid confusion with file comments. - * Returned field must be free()d by caller. +/* + * Escapes the field content string to avoid confusion with file comments. + * Returned field must be free()d by caller. */ static char *escape(const char *str) { @@ -87,12 +87,12 @@ static char *escape(const char *str) ++ptr; } - // Copy the input string to the resultant string, and escape all + // Copy the input string to the resultant string, and escape all // occurences of \# and #. char *result = (char*)malloc(strlen(str) + 1 + count); if (!result) error_msg_and_die("Memory error while escaping a field."); - + const char *src = str; char *dest = result; newline = true; @@ -109,15 +109,15 @@ static char *escape(const char *str) newline = (*src == '\n'); *dest++ = *src++; } - *dest = '\0'; + *dest = '\0'; return result; } /* - * Removes all comment lines, and unescapes the string previously escaped - * by escape(). Works in-place. + * Removes all comment lines, and unescapes the string previously escaped + * by escape(). Works in-place. */ -static char *remove_comments_and_unescape(char *str) +static void remove_comments_and_unescape(char *str) { char *src = str, *dest = str; bool newline = true; @@ -125,7 +125,7 @@ static char *remove_comments_and_unescape(char *str) { if (newline) { - if (*src == '#') + if (*src == '#') { // Skip the comment line! while (*src && *src != '\n') ++src; @@ -136,25 +136,25 @@ static char *remove_comments_and_unescape(char *str) ++src; continue; } - else if (*src == '\\' && - (*(src + 1) == '#' || + else if (*src == '\\' && + (*(src + 1) == '#' || (*(src + 1) == '\\' && *(src + 2) == '#'))) { ++src; // Unescape escaped char. } } - + newline = (*src == '\n'); *dest++ = *src++; } *dest = '\0'; } -/* +/* * Writes a field of crash report to a file. * Field must be writable. */ -static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, +static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, const char *field, const char *description) { const map_crash_report_t::const_iterator it = report.find(field); @@ -168,9 +168,9 @@ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, if (it->second[CD_TYPE] == CD_SYS) { error_msg("Cannot write field %s because it is a system value\n", field); - return; + return; } - + fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str()); fprintf(fp, "%s\n", description); @@ -182,8 +182,8 @@ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report, free(escaped_content); } -/* - * Saves the crash report to a file. +/* + * Saves the crash report to a file. * Parameter 'fp' must be opened before write_crash_report is called. * Returned value: * If the report is successfully stored to the file, a zero value is returned. @@ -194,7 +194,7 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp) fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); - write_crash_report_field(fp, report, CD_COMMENT, + write_crash_report_field(fp, report, CD_COMMENT, _("# Describe the circumstances of this crash below.")); write_crash_report_field(fp, report, CD_REPRODUCE, _("# How to reproduce the crash?")); @@ -210,19 +210,19 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp) write_crash_report_field(fp, report, FILENAME_PACKAGE, _("# Package")); write_crash_report_field(fp, report, FILENAME_REASON, _("# Reason of crash")); write_crash_report_field(fp, report, FILENAME_RELEASE, _("# Release string of the operating system")); - + return 0; } -/* +/* * Updates appropriate field in the report from the text. The text can - * contain multiple fields. + * contain multiple fields. * Returns: * 0 if no change to the field was detected. * 1 if the field was changed. * Changes to read-only fields are ignored. */ -static int read_crash_report_field(const char *text, map_crash_report_t &report, +static int read_crash_report_field(const char *text, map_crash_report_t &report, const char *field) { char separator[strlen("\n" FIELD_SEP) + strlen(field) + 2]; // 2 = '\n\0' @@ -236,9 +236,9 @@ static int read_crash_report_field(const char *text, map_crash_report_t &report, const char *end = strstr(textfield, "\n" FIELD_SEP); if (!end) length = strlen(textfield); - else + else length = end - textfield; - + const map_crash_report_t::iterator it = report.find(field); if (it == report.end()) { @@ -249,7 +249,7 @@ static int read_crash_report_field(const char *text, map_crash_report_t &report, if (it->second[CD_TYPE] == CD_SYS) { error_msg("Cannot update field %s because it is a system value.\n", field); - return 0; + return 0; } // Do not change noneditable fields. @@ -275,12 +275,12 @@ static int read_crash_report_field(const char *text, map_crash_report_t &report, return 1; } -/* - * Updates the crash report 'report' from the text. The text must not contain - * any comments. +/* + * Updates the crash report 'report' from the text. The text must not contain + * any comments. * Returns: * 0 if no field was changed. - * 1 if any field was changed. + * 1 if any field was changed. * Changes to read-only fields are ignored. */ static int read_crash_report(map_crash_report_t &report, const char *text) @@ -306,20 +306,20 @@ static int read_crash_report(map_crash_report_t &report, const char *text) int launch_editor(const char *path) { const char *editor, *terminal; - + editor = getenv("ABRT_EDITOR"); if (!editor) editor = getenv("VISUAL"); if (!editor) editor = getenv("EDITOR"); - + terminal = getenv("TERM"); if (!editor && (!terminal || !strcmp(terminal, "dumb"))) { error_msg(_("Terminal is dumb but no VISUAL nor EDITOR defined.")); return 1; } - + if (!editor) editor = "vi"; @@ -367,7 +367,7 @@ int report(const char *uuid, bool always) error_msg("could not close '%s'", filename); return 2; } - + // Start a text editor on the temporary file. launch_editor(filename); @@ -394,7 +394,7 @@ int report(const char *uuid, bool always) remove_comments_and_unescape(text); // Updates the crash report from the file text. - int report_changed = read_crash_report(cr, text); + int report_changed = read_crash_report(cr, text); if (report_changed) puts(_("\nThe report has been updated.")); else -- cgit